{
    "Function": "slitherConstructorConstantVariables",
    "File": "src/Facets/HopFacet.sol",
    "Parent Contracts": [
        "src/Facets/Swapper.sol",
        "src/Interfaces/ILiFi.sol"
    ],
    "High-Level Calls": [],
    "Internal Calls": [
        "keccak256(bytes)"
    ],
    "Library Calls": [],
    "Low-Level Calls": [],
    "Code": "contract HopFacet is ILiFi, Swapper {\n    /* ========== Storage ========== */\n\n    bytes32 internal constant NAMESPACE = keccak256(\"com.lifi.facets.hop\");\n    struct Storage {\n        mapping(string => IHopBridge.BridgeConfig) hopBridges;\n        uint256 hopChainId;\n    }\n\n    /* ========== Types ========== */\n\n    struct HopData {\n        string asset;\n        address recipient;\n        uint256 chainId;\n        uint256 amount;\n        uint256 bonderFee;\n        uint256 amountOutMin;\n        uint256 deadline;\n        uint256 destinationAmountOutMin;\n        uint256 destinationDeadline;\n    }\n\n    /* ========== Init ========== */\n\n    function initHop(\n        string[] memory _tokens,\n        IHopBridge.BridgeConfig[] memory _bridgeConfigs,\n        uint256 _chainId\n    ) external {\n        Storage storage s = getStorage();\n        LibDiamond.enforceIsContractOwner();\n\n        for (uint8 i; i < _tokens.length; i++) {\n            s.hopBridges[_tokens[i]] = _bridgeConfigs[i];\n        }\n        s.hopChainId = _chainId;\n    }\n\n    /* ========== Public Bridge Functions ========== */\n\n    /**\n     * @notice Bridges tokens via Hop Protocol\n     * @param _lifiData data used purely for tracking and analytics\n     * @param _hopData data specific to Hop Protocol\n     */\n    function startBridgeTokensViaHop(LiFiData memory _lifiData, HopData calldata _hopData) public payable {\n        address sendingAssetId = _bridge(_hopData.asset).token;\n\n        if (sendingAssetId == address(0)) require(msg.value == _hopData.amount, \"ERR_INVALID_AMOUNT\");\n        else {\n            uint256 _sendingAssetIdBalance = LibAsset.getOwnBalance(sendingAssetId);\n            LibAsset.transferFromERC20(sendingAssetId, msg.sender, address(this), _hopData.amount);\n            require(\n                LibAsset.getOwnBalance(sendingAssetId) - _sendingAssetIdBalance == _hopData.amount,\n                \"ERR_INVALID_AMOUNT\"\n            );\n        }\n\n        _startBridge(_hopData);\n\n        emit LiFiTransferStarted(\n            _lifiData.transactionId,\n            _lifiData.integrator,\n            _lifiData.referrer,\n            _lifiData.sendingAssetId,\n            _lifiData.receivingAssetId,\n            _lifiData.receiver,\n            _lifiData.amount,\n            _lifiData.destinationChainId,\n            block.timestamp\n        );\n    }\n\n    /**\n     * @notice Performs a swap before bridging via Hop Protocol\n     * @param _lifiData data used purely for tracking and analytics\n     * @param _swapData an array of swap related data for performing swaps before bridging\n     * @param _hopData data specific to Hop Protocol\n     */\n    function swapAndStartBridgeTokensViaHop(\n        LiFiData memory _lifiData,\n        LibSwap.SwapData[] calldata _swapData,\n        HopData memory _hopData\n    ) public payable {\n        address sendingAssetId = _bridge(_hopData.asset).token;\n\n        uint256 _sendingAssetIdBalance = LibAsset.getOwnBalance(sendingAssetId);\n\n        // Swap\n        _executeSwaps(_lifiData, _swapData);\n\n        uint256 _postSwapBalance = LibAsset.getOwnBalance(sendingAssetId) - _sendingAssetIdBalance;\n\n        require(_postSwapBalance > 0, \"ERR_INVALID_AMOUNT\");\n\n        _hopData.amount = _postSwapBalance;\n\n        _startBridge(_hopData);\n\n        emit LiFiTransferStarted(\n            _lifiData.transactionId,\n            _lifiData.integrator,\n            _lifiData.referrer,\n            _lifiData.sendingAssetId,\n            _lifiData.receivingAssetId,\n            _lifiData.receiver,\n            _lifiData.amount,\n            _lifiData.destinationChainId,\n            block.timestamp\n        );\n    }\n\n    /* ========== Internal Functions ========== */\n\n    /**\n     * @dev Conatains the business logic for the bridge via Hop Protocol\n     * @param _hopData data specific to Hop Protocol\n     */\n    function _startBridge(HopData memory _hopData) internal {\n        Storage storage s = getStorage();\n        address sendingAssetId = _bridge(_hopData.asset).token;\n\n        address bridge;\n        if (s.hopChainId == 1) {\n            bridge = _bridge(_hopData.asset).bridge;\n        } else {\n            bridge = _bridge(_hopData.asset).ammWrapper;\n        }\n\n        // Do HOP stuff\n        require(s.hopChainId != _hopData.chainId, \"Cannot bridge to the same network.\");\n\n        // Give Hop approval to bridge tokens\n        LibAsset.approveERC20(IERC20(sendingAssetId), bridge, _hopData.amount);\n\n        uint256 value = LibAsset.isNativeAsset(address(sendingAssetId)) ? _hopData.amount : 0;\n\n        if (s.hopChainId == 1) {\n            // Ethereum L1\n            IHopBridge(bridge).sendToL2{ value: value }(\n                _hopData.chainId,\n                _hopData.recipient,\n                _hopData.amount,\n                _hopData.destinationAmountOutMin,\n                _hopData.destinationDeadline,\n                address(0),\n                0\n            );\n        } else {\n            // L2\n            // solhint-disable-next-line check-send-result\n            IHopBridge(bridge).swapAndSend{ value: value }(\n                _hopData.chainId,\n                _hopData.recipient,\n                _hopData.amount,\n                _hopData.bonderFee,\n                _hopData.amountOutMin,\n                _hopData.deadline,\n                _hopData.destinationAmountOutMin,\n                _hopData.destinationDeadline\n            );\n        }\n    }\n\n    function _bridge(string memory _asset) internal view returns (IHopBridge.BridgeConfig memory) {\n        Storage storage s = getStorage();\n        return s.hopBridges[_asset];\n    }\n\n    function getStorage() internal pure returns (Storage storage s) {\n        bytes32 namespace = NAMESPACE;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            s.slot := namespace\n        }\n    }\n}"
}