Assessment reports>GammaSwap>Threat Models>Function: _liquidateExternally(uint256 tokenId, uint128[] amounts, uint256 lpTokens, address to, byte[] data)

Function: _liquidateExternally(uint256 tokenId, uint128[] amounts, uint256 lpTokens, address to, byte[] data)

Allows any caller to liquidate the existing loan using a flash loan of collateral tokens from the pool and/or CFMM LP tokens. Before the liquidation, the externalSwap function will be called. After that, a check will be made that enough tokens have been deposited. Allows only full liquidation of the loan.

Inputs

  • tokenId

    • Validation: There is no verification that the corresponding _loan for this tokenId exists.

    • Impact: A tokenId referring to an existing _loan. Not necessary msg.sender is owner of _loan, so the caller can choose any existing loan.

  • amounts

    • Validation: There is a check that amount <= s.TOKEN_BALANCE inside externalSwap->sendAndCalcCollateralLPTokens->sendToken function.

    • Impact: Amount of tokens from the pool to flash loan.

  • lpTokens

    • Validation: There is a check that lpTokens <= s.LP_TOKEN_BALANCE inside externalSwap->sendCFMMLPTokens->sendToken function

    • Impact: Amount of CFMM LP tokens being flash loaned.

  • to

    • Validation: Cannot be zero address.

    • Impact: Address that will receive the collateral tokens and/or lpTokens in flash loan.

  • data

    • Validation: No checks.

    • Impact: Custom user data. It is passed to the externalCall.

Branches and code coverage (including function calls)

The part of _liquidateExternally tests are skipped.

Intended branches

Negative behavior

Function call analysis

  • externalSwap(_loan, s.cfmm, amounts, lpTokens, to, data) -> sendAndCalcCollateralLPTokens(to, amounts, lastCFMMTotalSupply) -> sendToken(IERC20(tokens[i]), to, amounts[i], s.TOKEN_BALANCE[i], type(uint128).max) -> GammaSwapLibrary.safeTransfer(token, to, amount)

    • External/Internal? External.

    • Argument control? to and amount.

    • Impact: The caller can transfer any number of tokens that is less than s.TOKEN_BALANCE[i], but they must return the same or a larger amount after the externalCall function call; it will be checked inside the updateCollateral function.

  • externalSwap(_loan, s.cfmm, amounts, lpTokens, to, data) -> sendCFMMLPTokens(_cfmm, to, lpTokens) -> sendToken(IERC20(_cfmm), to, lpTokens, s.LP_TOKEN_BALANCE, type(uint256).max) -> GammaSwapLibrary.safeTransfer(token, to, amount)

    • External/Internal? External.

    • Argument control? to and amount.

    • Impact: The caller can transfer any number of tokens that is less than s.LP_TOKEN_BALANCE, but they must return the same or a larger amount after the externalCall function call; it will be checked inside the payLoanAndRefundLiquidator function.

  • externalSwap(_loan, s.cfmm, amounts, lpTokens, to, data) -> IExternalCallee(to).externalCall(msg.sender, amounts, lpTokens, data);

    • External/Internal? External.

    • Argument control? msg.sender, amounts, lpTokens, and data.

    • Impact: The reentrancy is not possible because the other important external functions have lock. If caller does not return enough amount of tokens, the transaction will be reverted.

  • externalSwap(_loan, s.cfmm, amounts, lpTokens, to, data) -> updateCollateral(_loan) -> GammaSwapLibrary.balanceOf(IERC20(tokens[i]), address(this)); -> address(_token).staticcall(abi.encodeWithSelector(_token.balanceOf.selector, _address))

    • Impact: Return the current token balance of this contract. This balance will be compared with the last tokenBalance[i] value; if the balance was increased, the _loan.tokensHeld and s.TOKEN_BALANCE will be increased too. But if the balance was decreased, the withdrawn value will be checked that it is no more than tokensHeld[i] (available collateral) and the _loan.tokensHeld and s.TOKEN_BALANCE will be increased.

  • payLoanAndRefundLiquidator(tokenId, tokensHeld, loanLiquidity, 0, true) -> GammaSwapLibrary.safeTransfer(IERC20(s.cfmm), msg.sender, lpRefund);

    • External/Internal? External.

    • Argument control? No.

    • Impact: The user should not control the lpRefund value. Transfer the remaining part of CFMMLPTokens.

Zellic © 2024Back to top ↑