MEDIUM severity: The vulnerability lies in the rebalancing mechanism of `mTOFTs` that hold native tokens. Specificall. The vulnerability lies in the rebalancing mechanism of `mTOFTs` that hold native tokens. Specifically, when the `routerETH` contract rebalances the ETH, it does not call the `sgReceive` function, leaving the ETH hanging inside the `mTOFT` contract. This can be exploited to steal all the ETH.\n\nThe...

Vulnerable code:
```\nif (address(this).balance < _amount) {\n    revert ExceedsBalance();\n}\n\nuint256 valueAmount = msg.value + _amount;\nrouterETH.swapETH(\n    value: valueAmount,\n    _dstChainId,\n    payable(this),\n    abi.encodePacked(connectedOFTs[_oft][_dstChainId].dstOft),\n    _amount,\n    _computeMinAmount(_amount, _slippage)\n);\n```\n```\nfunction sgReceive(\n    uint16,\n    bytes memory,\n    uint256,\n    address,\n    uint256 amountLD,\n    bytes memory\n) external payable {\n    if (msg.sender!= _stargateRouter) {\n        revert mTOFT_NotAuthorized();\n    }\n\n    if (erc20 == address(0)) {\n        vault.depositNative{value: amountLD}();\n    } else {\n        IERC20(erc20).safeTransfer(address(vault), amountLD);\n    }\n}\n```\n```\nfunction swapETH(\n    uint16 _dstChainId, \n    address payable _refundAddress, \n    bytes calldata _toAddress, \n    uint256 _amountLD, \n    uint256 _minAmountLD\n) external payable {\n    require(msg.value > _amountLD, "Stargate: msg.value must be > _amountLD");\n\n    IStargateEthVault(stargateEthVault).deposit{value: _amountLD}();\n    IStargateEthVault(stargateEthVault).approve(address(stargateRouter), _amountLD);\n\n    uint256 messageFee = msg.value - _amountLD;\n\n    stargateRouter.swap{value: messageFee}(\n        _dstChainId, \n        poolId, \n        poolId, \n        _refundAddress, \n        _amountLD, \n        _minAmountLD, \n        IStargateRouter.lzTxObj(0, 0, "0x"), \n        _toAddress, \n        bytes("")\n    );\n}\n```\n```\nfunction lzReceive(\n    uint16 _srcChainId,\n    bytes memory _srcAddress,\n    uint64 _nonce,\n    bytes memory _payload\n) external override {\n    if (functionType == TYPE_SWAP_REMOTE) {\n        (\n            uint8 _functionType,\n            uint256 srcPoolId,\n            uint256 dstPoolId,\n            uint256 dstGasForCall,\n            Pool.CreditObj memory c,\n            Pool.SwapObj memory s,\n            bytes memory to,\n            bytes memory payload\n        ) = abi.decode(_payload, (uint8, uint256, uint256, uint256, Pool.CreditObj, Pool.SwapObj, bytes, bytes));\n        address toAddress;\n        assembly {\n            toAddress := mload(add(to, 20))\n        }\n        router.creditChainPath(_srcChainId, srcPoolId, dstPoolId, c);\n        router.swapRemote(_srcChainId, _srcAddress, _nonce, srcPoolId, dstPoolId, dstGasForCall, toAddress, s, payload);\n    }\n}\n```\n```\nfunction _swapRemote(\n    uint16 _srcChainId,\n    bytes memory _srcAddress,\n    uint256 _nonce,\n    uint256 _srcPoolId,\n    uint256 _dstPoolId,\n    uint256 _dstGasForCall,\n    address _to,\n    Pool.SwapObj memory _s,\n    bytes memory _payload\n) internal {\n    Pool pool = _getPool(_dstPoolId);\n\n    try pool.swapRemote(_srcChainId, _srcPoolId, _to, _s) {\n        uint256 amountLD;\n\n        if (_payload.length > 0) {\n            try IStargateReceiver(_to).sgReceive{gas: _dstGasForCall}(_srcChainId, _srcAddress, _nonce, pool.token(), amountLD, _payload) {\n                // do nothing\n            } catch (bytes memory reason) {\n                cachedSwapLookup[_srcChainId][_srcAddress][_nonce] = CachedSwap(pool.token(), amountLD, _to, _payload);\n                emit CachedSwapSaved(_srcChainId, _srcAddress, _nonce, pool.token(), amountLD, _to, _payload, reason);\n            }\n        }\n    } catch {\n        revertLookup[_srcChainId][_srcAddress][_nonce] = abi.encode(\n            TYPE_SWAP_REMOTE_RETRY,\n            _srcPoolId,\n            _dstPoolId,\n            _dstGasForCall,\n            _to,\n            _s,\n            _payload\n        );\n        emit Revert(TYPE_SWAP_REMOTE_RETRY, _srcChainId, _srcAddress, _nonce);\n    }\n}\n```\n```\nfunction sendPacket(LZSendParam calldata _lzSendParam, bytes calldata _composeMsg)\n    external\n    payable\n    returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt)\n{\n    (uint256 amountDebitedLD, uint256 amountToCreditLD) =\n        _debit(_lzSendParam.sendParam.amountLD, _lzSendParam.sendParam.minAmountLD, _lzSendParam.sendParam.dstEid);\n\n    (bytes memory message, bytes memory options) =\n        _buildOFTMsgAndOptions(_lzSendParam.sendParam, _lzSendParam.extraOptions, _composeMsg, amountToCreditLD);\n\n    msgReceipt = _lzSend(_lzSendParam.sendParam.dstEid, message, options, _lzSendParam.fee, _lzSendParam.refundAddress);\n\n    oftReceipt = OFTReceipt(amountDebitedLD, amountToCreditLD);\n\n    emit OFTSent(msgReceipt.guid, _lzSendParam.sendParam.dstEid, msg.sender, amountDebitedLD);\n}\n```