Assessment reports>SyncSwap>Threat Models>flashLoan

Function: flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, byte[] userData)

Allows to take a flash loan from the vault.

Inputs

  • receiver

    • Control: Arbitrary.

    • Constraints: None.

    • Impact: Determines the contract that receives the flash loan.

  • token

    • Control: Arbitrary.

    • Constraints: None.

    • Impact: Determines the asset to be borrowed.

  • amount

    • Control: Arbitrary.

    • Constraints: Must be lower of equal to the vault balance.

    • Impact: Determines the amount to be borrowed.

  • userData

    • Control: Arbitrary.

    • Constraints: None.

    • Impact: Data passed to the borrower contract.

Branches and code coverage (including function calls)

Intended branches

Transfers the borrowed amount to the contract, invokes its callback, and checks that 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.

Function call analysis

  • rootFunction -> 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 -> _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 -> receiver.onFlashLoan(msg.sender, token, amount, feeAmount, userData)

    • What is controllable? token, amount, userData.

    • If return value controllable, how is it used and how can it go wrong? Return value must be ERC3156_CALLBACK_SUCCESS to signal successful execution.

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

  • rootFunction -> 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 ↑