Assessment reports>Avon>Low findings>The function ,previewBorrow, fails when matched orders exceed ,MAX_MATCH_DETAILS
Category: Business Logic

The function previewBorrow fails when matched orders exceed MAX_MATCH_DETAILS

Low Impact
Low Severity
Low Likelihood

Description

The functions _previewMatchBorrow and _previewMatchBorrowWithExactCollateral return a struct PreviewMatchedOrder, which records the detailed information of matched orders, the total amount of matched loan tokens (totalMatched), and the total match count. However, when the total match count exceeds MAX_MATCH_DETAILS, the order details will no longer be recorded. As a result, the totalCount may be greater than the length of the order details arrays.

struct PreviewMatchedOrder {
    address[] counterParty;
    uint256[] amounts;
    uint256[] irs;
    uint256[] ltvs;
    uint256 totalMatched;
    uint256 totalCount;
}

Impact

When previewMatchedOrders.totalMatched is greater than 0, the function previewBorrow iterates through the order details, but the maximum value of the index is totalCount - 1. Therefore, if the actual number of matched orders exceeds MAX_MATCH_DETAILS, the following code will fail due to an out-of-bounds array access.

function previewBorrow(PreviewBorrowParams memory previewBorrowParams)
    external
    view
    returns (
        // [...]
    )
{
    if (previewBorrowParams.isMarketOrder) {
        (previewBorrowParams.rate,) = lenderTree._getBestLenderRate();
        previewBorrowParams.ltv = OrderbookLib.MIN_LTV;
    }
    previewMatchedOrders = previewBorrowParams.isCollateral
        ? lenderTree._previewMatchBorrowWithExactCollateral(
            // [...]
        )
        : lenderTree._previewMatchBorrow(previewBorrowParams.rate, previewBorrowParams.ltv, previewBorrowParams.amount);
    // [...]
    if (previewMatchedOrders.totalMatched > 0) {
        uint256 matchedOrderCount = previewMatchedOrders.totalCount;
        for (uint256 i; i < matchedOrderCount; i++) {
            previewBorrowParams.isCollateral
                ? loanTokenAmount += previewMatchedOrders.amounts[i]
                : collateralRequired += IPoolImplementation(previewMatchedOrders.counterParty[i]).previewBorrow(
                    previewBorrowParams.borrower, previewMatchedOrders.amounts[i], previewBorrowParams.collateralBuffer
                );
        }
        // [...]
    }
}

Recommendations

Consider using another variable to record the actual length of the order details arrays.

Remediation

This issue has been acknowledged by AVON TECH LTD, and fixes were implemented in the following commits:

Zellic © 2025Back to top ↑