Assessment reports>Wasabi Perps>Threat Model>openPosition

Function: openPosition(OpenPositionRequest _request, Signature _signature)

This function can be used to open a position, long or short, according to the data passed in the _request argument.

Inputs

  • _request

    • Control: Unclear; this argument is validated and signed by an off-chain, out-of-scope component.

    • Constraints:

      • id must not be already used.

      • currency could be anything except a base token.

      • targetCurrency must be a base token.

      • downPayment is not directly constrained by the smart contract.

      • principal must be at most the vault principal balance and is also checked to be no more than the computed maximum principal amount to prevent overleveraging.

      • minTargetAmount is not directly constrained and is used to implement antislippage checks.

      • expiration must be after the current block.timestamp.

      • fee is not constrained.

      • functionCallDataList is not constrained.

    • Impact: Specifies all the parameters of the position.

  • _signature

    • Control: Arbitrary.

    • Constraints: Must be a valid signature of _request from the contract owner.

    • Impact: Signature authorizing the operation.

Branches and code coverage

Intended branches

  • After performing validation of the _request argument, it executes the calls specified in functionCallDataList, which are intended to grant approval and call Uniswap to perform the needed trade, selling the shorted principal asset for the collateral. After checking the received collateral amount and the principal, the hash identifying the position is recorded in storage.

Negative behavior

  • Reverts if the signature is invalid.

  • Reverts if the position ID is already used.

  • Reverts if functionCallDataList is empty.

  • Reverts if the request is expired.

  • Reverts if the currency is a base token.

  • Reverts if the targetCurrency is not a base token.

  • Reverts if receiving the payment fails (for raw ETH).

  • Reverts if receiving the payment fails (for WETH / other ERC-20).

  • Reverts if the requested principal is more than the available balance.

  • Reverts if the received collateral is less than the minumum specified in the request.

  • Reverts if the requested principal would overleverage the user.

Function call analysis

  • this._validateOpenPositionRequest(_request, _signature) -> PerpUtils.receivePayment(this.isLongPool ? _request.currency : _request.targetCurrency, _request.downPayment + _request.fee, this.addressProvider.getWethAddress(), msg.sender)

    • What is controllable? targetCurrency and amount (to some extent).

    • If the return value is controllable, how is it used and how can it go wrong? Not used.

    • What happens if it reverts, reenters or does other unusual control flow? Reentrancy is prevented via nonReentrant modifier (apart from admin-only functions).

  • principalToken.balanceOf(address(this))

    • What is controllable? principalToken is signed, but it must be validated by the off-chain component.

    • If the return value is controllable, how is it used and how can it go wrong? Used as the balance of the principal token before the swap.

    • What happens if it reverts, reenters or does other unusual control flow? Reentrancy is prevented via nonReentrant modifier (apart from admin-only functions).

  • collateralToken.balanceOf(address(this))

    • What is controllable? collateralToken is signed, but it must be validated by the off-chain component.

    • If the return value is controllable, how is it used and how can it go wrong? Used as the collateral balance before the swap.

    • What happens if it reverts, reenters or does other unusual control flow? Reentrancy is prevented via nonReentrant modifier (apart from admin-only functions).

  • PerpUtils.executeFunctions(_request.functionCallDataList)

    • What is controllable? Nothing directly — argument provided by the off-chain component.

    • If the return value is controllable, how is it used and how can it go wrong? Not used.

    • What happens if it reverts, reenters or does other unusual control flow? Reentrancy is prevented via nonReentrant modifier (apart from admin-only functions).

  • collateralToken.balanceOf(address(this))

    • What is controllable? As above, collateralToken is signed, but it must be validated by the off-chain component.

    • If the return value is controllable, how is it used and how can it go wrong? Used as the collateral balance after the swap.

    • What happens if it reverts, reenters or does other unusual control flow? Reentrancy is prevented via nonReentrant modifier (apart from admin-only functions).

  • this.addressProvider.getDebtController().computeMaxPrincipal(_request.targetCurrency, _request.currency, swappedDownPaymentAmount)

    • What is controllable? targetCurrency and currency, to the extent permitted by the off-chain component. They are currently unused.

    • If the return value is controllable, how is it used and how can it go wrong? Used to limit the maximum amount of principal the user can request.

    • What happens if it reverts, reenters or does other unusual control flow? The caller cannot cause the call to reenter or revert.

  • principalToken.balanceOf(address(this))

    • What is controllable? principalToken is signed and validated by the off-chain component.

    • If the return value is controllable, how is it used and how can it go wrong? Used to determine the amount of principal gained from the swap.

    • What happens if it reverts, reenters or does other unusual control flow? Reentrancy is prevented via nonReentrant modifier (apart from admin-only functions).

Zellic © 2024Back to top ↑