Assessment reports>SyncSwap>Threat Models>flashLoanMultiple

Function: flashLoanMultiple(IFlashLoanRecipient recipient, address[] tokens, uint256[] amounts, byte[] userData)

Allows to take a flash loan from the vault, taking multiple assets at the same time.

Inputs

  • recipient

    • Control: Arbitrary.

    • Constraints: None.

    • Impact: Determines the recipient that receives the borrowed assets.

  • tokens

    • Control: Arbitrary.

    • Constraints: Elements must be sorted and unique.

    • Impact: Determines the assets to be borrowed.

  • amounts

    • Control: Arbitrary.

    • Constraints: amounts.length == tokens.length; every amount is less than the corresponding vault balance.

    • Impact: Determines the amounts to be borrowed.

  • userData

    • Control: Arbitrary.

    • Constraints: None.

    • Impact: Arbitrary data passed to the recipient.

Branches and code coverage (including function calls)

Intended branches

Sends the borrowed funds to the recipient, invokes the recipient, and checks that the funds and interests are returned.

Negative behavior

Reverts if the vault balance is not enough to cover the requested loan.

Reverts if the borrower does not return ERC3156_CALLBACK_SUCCESS.

Reverts if the flash loan is not repaid.

Reverts if amounts.length != tokens.length.

Reverts if the vault does not have sufficient balance to cover the requested loan.

Function call analysis

  • rootFunction -> preLoanBalances[i] = IERC20(token).balanceOf(address(this))

    • What is controllable? token.

    • If return value controllable, how is it used and how can it go wrong? Used as the preloan balance of the contract, not controllable for legitimate tokens.

    • What happens if it reverts, reenters, or does other unusual control flow? Reverts are bubbled up; reentrancy is prevented via the nonReentrant modifier.

  • rootFunction -> feeAmounts[i] = _calculateFlashLoanFeeAmount(amount)

    • What is controllable? amount.

    • If return value controllable, how is it used and how can it go wrong? The function returns the interests of the flash loan, proportional to amount.

    • What happens if it reverts, reenters, or does other unusual control flow? Reverts (e.g., due to overflow) are bubbled up; reentrancy is not a concern.

  • rootFunction -> TransferHelper.safeTransfer(token, address(receiver), amount)

    • What is controllable? token, receiver, amount.

    • If return value controllable, how is it used and how can it go wrong? The return value of the internal call must be bool(true).

    • What happens if it reverts, reenters, or does other unusual control flow? Reverts are bubbled up; reentrancy is prevented via the nonReentrant modifier.

  • rootFunction -> recipient.receiveFlashLoan(tokens, amounts, feeAmounts, userData)

    • What is controllable? tokens, amounts, userData.

    • If return value controllable, how is it used and how can it go wrong? N/A.

    • What happens if it reverts, reenters, or does other unusual control flow? Reverts are bubbled up; reentrancy is prevented via the nonReentrant modifier.

  • rootFunction -> postLoanBalance = IERC20(token).balanceOf(address(this))

    • What is controllable? token.

    • If return value controllable, how is it used and how can it go wrong? Used as the postloan balance of the contract, not controllable for legitimate tokens.

    • What happens if it reverts, reenters, or does other unusual control flow? Reverts are bubbled up; reentrancy is prevented via the nonReentrant modifier.

  • rootFunction -> _payFeeAmount(token, receivedFeeAmount)

    • What is controllable? token, receivedFeeAmount.

    • If return value controllable, how is it used and how can it go wrong? N/A.

    • What happens if it reverts, reenters, or does other unusual control flow? Reverts are bubbled up; reentrancy is prevented via the nonReentrant modifier.

Zellic © 2024Back to top ↑