Assessment reports>Maia DAO Ulysses Protocol>Threat Model>callOutSignedAndBridge

Function: callOutSignedAndBridge(bytes _params, DepositInput _dParams, GasParams _gParams, bool _hasFallbackToggled)

The function allows the execution of a cross-chain request, which involves locking funds into the localPort contract. On the Root chain, the Virtual Account contract associated with the caller will receive the _amount of global _hToken. Additionally, the caller can provide extra payload data to trigger functions of the Virtual Account on the Root chain.

Inputs

  • _params

    • Control: Full control by the caller.

    • Constraints: N/A.

    • Impact: Contains additional data for rootRouterAddress.executeSignedDepositSingle — can be empty.

  • _dParams

    • Control: Full control by the caller, who must own the corresponding amount of tokens.

    • Constraints: The localPort contract must be able to burn _dParams.hToken tokens and must have approval from the caller to transfer _dParams.token.

    • Impact: It includes _dParams.hToken, _dParams.token, _dParams.amount, and _dParams.deposit_dParams.hToken will be burned by the localPort contract, and _dParams.token will be transferred from the caller to the localPort contract.

  • _gParams

    • Control: Full control by the caller.

    • Constraints: There are no constraints.

    • Impact: These values are used to encode AdapterParameters data for the LayerZero relayer contract.

  • _hasFallbackToggled

    • Control: Full control by the caller.

    • Constraints: N/A.

    • Impact: If true, a fallback call will be performed after receiving the message in the Root chain.

Branches and code coverage

Intended branches

  • Check that the deposit was successful.

  • Check that the fallback call was performed.

Function call analysis

  • this._createDeposit(True, _depositNonce, msg.sender, _dParams.hToken, _dParams.token, _dParams.amount, _dParams.deposit) -> IBranchPort(this.localPortAddress).bridgeOut(msg.sender, _hToken, _token, _amount, _deposit)

    • What is controllable? The _dParams is controlled by the caller.

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

    • What happens if it reverts, reenters or does other unusual control flow? The function burns the _dParams._amount - _dParams._deposit amount of _dParams.hToken tokens from the caller's account. If _dParams.token is not the zero address, it transfers the _deposit amount of _dParams.token tokens from the caller to the localPortAddress contract address.

  • this._performCall(address payable(msg.sender), payload, _gParams, _hasFallbackToggled ? BridgeAgentConstants.BRANCH_BASE_CALL_OUT_SIGNED_DEPOSIT_SINGLE_GAS + BridgeAgentConstants.BASE_FALLBACK_GAS : BridgeAgentConstants.BRANCH_BASE_CALL_OUT_SIGNED_DEPOSIT_SINGLE_GAS) -> ILayerZeroEndpoint(this.lzEndpointAddress).send{value: msg.value}

    • What is controllable? The payload is partly controlled; the caller controls _dParams.hToken, _dParams.token, _dParams.amount, and _dParams.deposit.

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

    • What happens if it reverts, reenters or does other unusual control flow? The function can revert if the caller does not provide enough fee payment or if rootChainId is unknown. However, the caller does not control rootChainId.

  • this._performCall(address payable(msg.sender), payload, _gParams, _hasFallbackToggled ? BridgeAgentConstants.BRANCH_BASE_CALL_OUT_SIGNED_DEPOSIT_SINGLE_GAS + BridgeAgentConstants.BASE_FALLBACK_GAS : BridgeAgentConstants.BRANCH_BASE_CALL_OUT_SIGNED_DEPOSIT_SINGLE_GAS) -> IRootBridgeAgent(this.rootBridgeAgentAddress).lzReceive{value: msg.value}

    • What is controllable? The payload is partly controlled by the initial caller. The initial caller controls _dParams.hToken, _dParams.token, _dParams.amount, and _dParams.deposit.

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

    • What happens if it reverts, reenters or does other unusual control flow? This function call is a part of the cross-chain--message transferring process, so it will be executed in a different transaction and on a different chain than the original call. Since all the logic for message processing is executed within the excessivelySafeCall function, in case of a revert, the message will not be saved for resending and all native tokens from this contract will be transferred to the rootPortAddress contract. But if either transfers revert, the message will be saved for resending. However, it will also be possible to skip this message using the forceResumeReceive function. During payload processing, the function can revert if _dParams.hToken is not set as a trusted local token in _srcChainId and if _dParams.token is not set as the underlying token for _dParams.hToken from _srcChainId.

Zellic © 2024Back to top ↑