creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/Facets/MayanFacet.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { IMayan } from \"../Interfaces/IMayan.sol\";\nimport { UnsupportedChainId } from \"../Errors/GenericErrors.sol\";\n\n/// @title Mayan Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Mayan Bridge\n/// @custom:version 1.0.0\ncontract MayanFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n    /// Storage ///\n\n    bytes32 internal constant NAMESPACE = keccak256(\"com.lifi.facets.mayan\");\n    address internal constant NON_EVM_ADDRESS =\n        0x11f111f111f111F111f111f111F111f111f111F1;\n    bytes32 internal constant MAYAN_AUCTION_ADDRESS =\n        0x3383cb0c0c60fc12b717160b699a55db62c56baed78a0ff9ebed68e1b003d38c;\n    uint16 internal constant MAYAN_CHAIN_ID = 1;\n\n    IMayan public immutable mayan;\n\n    /// Types ///\n\n    struct Storage {\n        mapping(uint256 => uint16) wormholeChainId;\n    }\n\n    struct Config {\n        uint256 chainId;\n        uint16 wormholeChainId;\n    }\n\n    /// @dev Optional bridge specific struct\n    /// @param mayanAddr The address of the Mayan Bridge\n    /// @param referrer The referrer address\n    /// @param tokenOutAddr The address of the token to be received\n    /// @param receiver The address of the receiver\n    /// @param swapFee The swap fee\n    /// @param redeemFee The redeem fee\n    /// @param refundFee The refund fee\n    /// @param transferDeadline The transfer deadline\n    /// @param swapDeadline The swap deadline\n    /// @param amountOutMin The minimum amount out\n    /// @param destChainId The (wormhole) destination chain id\n    /// @param unwrap Whether to unwrap the asset\n    /// @param gasDrop The gas drop\n    struct MayanData {\n        bytes32 mayanAddr;\n        bytes32 referrer;\n        bytes32 tokenOutAddr;\n        bytes32 receiver;\n        uint64 swapFee;\n        uint64 redeemFee;\n        uint64 refundFee;\n        uint256 transferDeadline;\n        uint64 swapDeadline;\n        uint64 amountOutMin;\n        bool unwrap;\n        uint64 gasDrop;\n    }\n\n    /// Events ///\n\n    event MayanInitialized(Config[] configs);\n    event MayanChainIdMapped(\n        uint256 indexed lifiChainId,\n        uint256 indexed wormholeChainId\n    );\n    event BridgeToNonEVMChain(\n        bytes32 indexed transactionId,\n        uint256 indexed destinationChainId,\n        bytes32 receiver\n    );\n\n    /// Constructor ///\n\n    /// @notice Constructor for the contract.\n    constructor(IMayan _mayan) {\n        mayan = _mayan;\n    }\n\n    /// Init ///\n\n    /// @notice Initialize local variables for the Wormhole Facet\n    /// @param configs Bridge configuration data\n    function initMayan(Config[] calldata configs) external {\n        LibDiamond.enforceIsContractOwner();\n\n        Storage storage sm = getStorage();\n\n        uint256 numConfigs = configs.length;\n        for (uint256 i = 0; i < numConfigs; i++) {\n            sm.wormholeChainId[configs[i].chainId] = configs[i]\n                .wormholeChainId;\n        }\n\n        emit MayanInitialized(configs);\n    }\n\n    /// External Methods ///\n\n    /// @notice Creates a mapping between a lifi chain id and a wormhole chain id\n    /// @param _lifiChainId lifi chain id\n    /// @param _wormholeChainId wormhole chain id\n    function setMayanChainIdMapping(\n        uint256 _lifiChainId,\n        uint16 _wormholeChainId\n    ) external {\n        LibDiamond.enforceIsContractOwner();\n        Storage storage sm = getStorage();\n        sm.wormholeChainId[_lifiChainId] = _wormholeChainId;\n        emit MayanChainIdMapped(_lifiChainId, _wormholeChainId);\n    }\n\n    /// @notice Bridges tokens via Mayan\n    /// @param _bridgeData The core information needed for bridging\n    /// @param _mayanData Data specific to Mayan\n    function startBridgeTokensViaMayan(\n        ILiFi.BridgeData memory _bridgeData,\n        MayanData calldata _mayanData\n    )\n        external\n        payable\n        nonReentrant\n        refundExcessNative(payable(msg.sender))\n        validateBridgeData(_bridgeData)\n        doesNotContainSourceSwaps(_bridgeData)\n        doesNotContainDestinationCalls(_bridgeData)\n    {\n        uint256 totalFees = _mayanData.swapFee +\n            _mayanData.redeemFee +\n            _mayanData.refundFee;\n\n        LibAsset.depositAsset(\n            _bridgeData.sendingAssetId,\n            _bridgeData.minAmount\n        );\n        _startBridge(_bridgeData, _mayanData, totalFees);\n    }\n\n    /// @notice Performs a swap before bridging via Mayan\n    /// @param _bridgeData The core information needed for bridging\n    /// @param _swapData An array of swap related data for performing swaps before bridging\n    /// @param _mayanData Data specific to Mayan\n    function swapAndStartBridgeTokensViaMayan(\n        ILiFi.BridgeData memory _bridgeData,\n        LibSwap.SwapData[] calldata _swapData,\n        MayanData calldata _mayanData\n    )\n        external\n        payable\n        nonReentrant\n        refundExcessNative(payable(msg.sender))\n        containsSourceSwaps(_bridgeData)\n        doesNotContainDestinationCalls(_bridgeData)\n        validateBridgeData(_bridgeData)\n    {\n        uint256 totalFees = _mayanData.swapFee +\n            _mayanData.redeemFee +\n            _mayanData.refundFee;\n        address assetId = _bridgeData.sendingAssetId;\n        _bridgeData.minAmount = _depositAndSwap(\n            _bridgeData.transactionId,\n            _bridgeData.minAmount,\n            _swapData,\n            payable(msg.sender),\n            LibAsset.isNativeAsset(assetId) ? 0 : totalFees\n        );\n        _startBridge(_bridgeData, _mayanData, totalFees);\n    }\n\n    /// Internal Methods ///\n\n    /// @dev Contains the business logic for the bridge via Mayan\n    /// @param _bridgeData The core information needed for bridging\n    /// @param _mayanData Data specific to Mayan\n    function _startBridge(\n        ILiFi.BridgeData memory _bridgeData,\n        MayanData calldata _mayanData,\n        uint256 _totalFees\n    ) internal {\n        uint16 whDestChainId = getWormholeChainId(\n            _bridgeData.destinationChainId\n        );\n\n        IMayan.RelayerFees memory relayerFees = IMayan.RelayerFees({\n            swapFee: _mayanData.swapFee,\n            redeemFee: _mayanData.redeemFee,\n            refundFee: _mayanData.refundFee\n        });\n\n        IMayan.Recepient memory recipient = IMayan.Recepient({\n            mayanAddr: _mayanData.mayanAddr,\n            mayanChainId: MAYAN_CHAIN_ID,\n            auctionAddr: MAYAN_AUCTION_ADDRESS,\n            destAddr: _mayanData.receiver,\n            destChainId: whDestChainId,\n            referrer: _mayanData.referrer,\n            refundAddr: _mayanData.receiver\n        });\n\n        IMayan.Criteria memory criteria = IMayan.Criteria({\n            transferDeadline: _mayanData.transferDeadline,\n            swapDeadline: _mayanData.swapDeadline,\n            amountOutMin: _mayanData.amountOutMin,\n            unwrap: _mayanData.unwrap,\n            gasDrop: _mayanData.gasDrop,\n            customPayload: \"\"\n        });\n\n        if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n            LibAsset.maxApproveERC20(\n                IERC20(_bridgeData.sendingAssetId),\n                address(mayan),\n                _bridgeData.minAmount\n            );\n\n            mayan.swap(\n                relayerFees,\n                recipient,\n                _mayanData.tokenOutAddr,\n                whDestChainId,\n                criteria,\n                _bridgeData.sendingAssetId,\n                _bridgeData.minAmount - _totalFees\n            );\n        } else {\n            mayan.wrapAndSwapETH{ value: _bridgeData.minAmount }(\n                relayerFees,\n                recipient,\n                _mayanData.tokenOutAddr,\n                whDestChainId,\n                criteria\n            );\n        }\n\n        if (_bridgeData.receiver == NON_EVM_ADDRESS) {\n            emit BridgeToNonEVMChain(\n                _bridgeData.transactionId,\n                _bridgeData.destinationChainId,\n                _mayanData.receiver\n            );\n        }\n\n        emit LiFiTransferStarted(_bridgeData);\n    }\n\n    /// @notice Gets the wormhole chain id for a given lifi chain id\n    /// @param _lifiChainId uint256 of the lifi chain ID\n    /// @return uint16 of the wormhole chain id\n    function getWormholeChainId(\n        uint256 _lifiChainId\n    ) private view returns (uint16) {\n        Storage storage sm = getStorage();\n        uint16 wormholeChainId = sm.wormholeChainId[_lifiChainId];\n        if (wormholeChainId == 0) revert UnsupportedChainId(_lifiChainId);\n        return wormholeChainId;\n    }\n\n    /// @dev fetch local storage\n    function getStorage() private 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}\n"
      },
      "src/Interfaces/ILiFi.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n    /// Structs ///\n\n    struct BridgeData {\n        bytes32 transactionId;\n        string bridge;\n        string integrator;\n        address referrer;\n        address sendingAssetId;\n        address receiver;\n        uint256 minAmount;\n        uint256 destinationChainId;\n        bool hasSourceSwaps;\n        bool hasDestinationCall;\n    }\n\n    /// Events ///\n\n    event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n    event LiFiTransferCompleted(\n        bytes32 indexed transactionId,\n        address receivingAssetId,\n        address receiver,\n        uint256 amount,\n        uint256 timestamp\n    );\n\n    event LiFiTransferRecovered(\n        bytes32 indexed transactionId,\n        address receivingAssetId,\n        address receiver,\n        uint256 amount,\n        uint256 timestamp\n    );\n\n    event LiFiGenericSwapCompleted(\n        bytes32 indexed transactionId,\n        string integrator,\n        string referrer,\n        address receiver,\n        address fromAssetId,\n        address toAssetId,\n        uint256 fromAmount,\n        uint256 toAmount\n    );\n\n    // Deprecated but kept here to include in ABI to parse historic events\n    event LiFiSwappedGeneric(\n        bytes32 indexed transactionId,\n        string integrator,\n        string referrer,\n        address fromAssetId,\n        address toAssetId,\n        uint256 fromAmount,\n        uint256 toAmount\n    );\n}\n"
      },
      "src/Libraries/LibDiamond.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n    bytes32 internal constant DIAMOND_STORAGE_POSITION =\n        keccak256(\"diamond.standard.diamond.storage\");\n\n    // Diamond specific errors\n    error IncorrectFacetCutAction();\n    error NoSelectorsInFace();\n    error FunctionAlreadyExists();\n    error FacetAddressIsZero();\n    error FacetAddressIsNotZero();\n    error FacetContainsNoCode();\n    error FunctionDoesNotExist();\n    error FunctionIsImmutable();\n    error InitZeroButCalldataNotEmpty();\n    error CalldataEmptyButInitNotZero();\n    error InitReverted();\n    // ----------------\n\n    struct FacetAddressAndPosition {\n        address facetAddress;\n        uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n    }\n\n    struct FacetFunctionSelectors {\n        bytes4[] functionSelectors;\n        uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n    }\n\n    struct DiamondStorage {\n        // maps function selector to the facet address and\n        // the position of the selector in the facetFunctionSelectors.selectors array\n        mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n        // maps facet addresses to function selectors\n        mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n        // facet addresses\n        address[] facetAddresses;\n        // Used to query if a contract implements an interface.\n        // Used to implement ERC-165.\n        mapping(bytes4 => bool) supportedInterfaces;\n        // owner of the contract\n        address contractOwner;\n    }\n\n    function diamondStorage()\n        internal\n        pure\n        returns (DiamondStorage storage ds)\n    {\n        bytes32 position = DIAMOND_STORAGE_POSITION;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            ds.slot := position\n        }\n    }\n\n    event OwnershipTransferred(\n        address indexed previousOwner,\n        address indexed newOwner\n    );\n\n    function setContractOwner(address _newOwner) internal {\n        DiamondStorage storage ds = diamondStorage();\n        address previousOwner = ds.contractOwner;\n        ds.contractOwner = _newOwner;\n        emit OwnershipTransferred(previousOwner, _newOwner);\n    }\n\n    function contractOwner() internal view returns (address contractOwner_) {\n        contractOwner_ = diamondStorage().contractOwner;\n    }\n\n    function enforceIsContractOwner() internal view {\n        if (msg.sender != diamondStorage().contractOwner)\n            revert OnlyContractOwner();\n    }\n\n    event DiamondCut(\n        IDiamondCut.FacetCut[] _diamondCut,\n        address _init,\n        bytes _calldata\n    );\n\n    // Internal function version of diamondCut\n    function diamondCut(\n        IDiamondCut.FacetCut[] memory _diamondCut,\n        address _init,\n        bytes memory _calldata\n    ) internal {\n        for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n            IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n            if (action == IDiamondCut.FacetCutAction.Add) {\n                addFunctions(\n                    _diamondCut[facetIndex].facetAddress,\n                    _diamondCut[facetIndex].functionSelectors\n                );\n            } else if (action == IDiamondCut.FacetCutAction.Replace) {\n                replaceFunctions(\n                    _diamondCut[facetIndex].facetAddress,\n                    _diamondCut[facetIndex].functionSelectors\n                );\n            } else if (action == IDiamondCut.FacetCutAction.Remove) {\n                removeFunctions(\n                    _diamondCut[facetIndex].facetAddress,\n                    _diamondCut[facetIndex].functionSelectors\n                );\n            } else {\n                revert IncorrectFacetCutAction();\n            }\n            unchecked {\n                ++facetIndex;\n            }\n        }\n        emit DiamondCut(_diamondCut, _init, _calldata);\n        initializeDiamondCut(_init, _calldata);\n    }\n\n    function addFunctions(\n        address _facetAddress,\n        bytes4[] memory _functionSelectors\n    ) internal {\n        if (_functionSelectors.length == 0) {\n            revert NoSelectorsInFace();\n        }\n        DiamondStorage storage ds = diamondStorage();\n        if (LibUtil.isZeroAddress(_facetAddress)) {\n            revert FacetAddressIsZero();\n        }\n        uint96 selectorPosition = uint96(\n            ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n        );\n        // add new facet address if it does not exist\n        if (selectorPosition == 0) {\n            addFacet(ds, _facetAddress);\n        }\n        for (\n            uint256 selectorIndex;\n            selectorIndex < _functionSelectors.length;\n\n        ) {\n            bytes4 selector = _functionSelectors[selectorIndex];\n            address oldFacetAddress = ds\n                .selectorToFacetAndPosition[selector]\n                .facetAddress;\n            if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n                revert FunctionAlreadyExists();\n            }\n            addFunction(ds, selector, selectorPosition, _facetAddress);\n            unchecked {\n                ++selectorPosition;\n                ++selectorIndex;\n            }\n        }\n    }\n\n    function replaceFunctions(\n        address _facetAddress,\n        bytes4[] memory _functionSelectors\n    ) internal {\n        if (_functionSelectors.length == 0) {\n            revert NoSelectorsInFace();\n        }\n        DiamondStorage storage ds = diamondStorage();\n        if (LibUtil.isZeroAddress(_facetAddress)) {\n            revert FacetAddressIsZero();\n        }\n        uint96 selectorPosition = uint96(\n            ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n        );\n        // add new facet address if it does not exist\n        if (selectorPosition == 0) {\n            addFacet(ds, _facetAddress);\n        }\n        for (\n            uint256 selectorIndex;\n            selectorIndex < _functionSelectors.length;\n\n        ) {\n            bytes4 selector = _functionSelectors[selectorIndex];\n            address oldFacetAddress = ds\n                .selectorToFacetAndPosition[selector]\n                .facetAddress;\n            if (oldFacetAddress == _facetAddress) {\n                revert FunctionAlreadyExists();\n            }\n            removeFunction(ds, oldFacetAddress, selector);\n            addFunction(ds, selector, selectorPosition, _facetAddress);\n            unchecked {\n                ++selectorPosition;\n                ++selectorIndex;\n            }\n        }\n    }\n\n    function removeFunctions(\n        address _facetAddress,\n        bytes4[] memory _functionSelectors\n    ) internal {\n        if (_functionSelectors.length == 0) {\n            revert NoSelectorsInFace();\n        }\n        DiamondStorage storage ds = diamondStorage();\n        // if function does not exist then do nothing and return\n        if (!LibUtil.isZeroAddress(_facetAddress)) {\n            revert FacetAddressIsNotZero();\n        }\n        for (\n            uint256 selectorIndex;\n            selectorIndex < _functionSelectors.length;\n\n        ) {\n            bytes4 selector = _functionSelectors[selectorIndex];\n            address oldFacetAddress = ds\n                .selectorToFacetAndPosition[selector]\n                .facetAddress;\n            removeFunction(ds, oldFacetAddress, selector);\n            unchecked {\n                ++selectorIndex;\n            }\n        }\n    }\n\n    function addFacet(\n        DiamondStorage storage ds,\n        address _facetAddress\n    ) internal {\n        enforceHasContractCode(_facetAddress);\n        ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n            .facetAddresses\n            .length;\n        ds.facetAddresses.push(_facetAddress);\n    }\n\n    function addFunction(\n        DiamondStorage storage ds,\n        bytes4 _selector,\n        uint96 _selectorPosition,\n        address _facetAddress\n    ) internal {\n        ds\n            .selectorToFacetAndPosition[_selector]\n            .functionSelectorPosition = _selectorPosition;\n        ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n            _selector\n        );\n        ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n    }\n\n    function removeFunction(\n        DiamondStorage storage ds,\n        address _facetAddress,\n        bytes4 _selector\n    ) internal {\n        if (LibUtil.isZeroAddress(_facetAddress)) {\n            revert FunctionDoesNotExist();\n        }\n        // an immutable function is a function defined directly in a diamond\n        if (_facetAddress == address(this)) {\n            revert FunctionIsImmutable();\n        }\n        // replace selector with last selector, then delete last selector\n        uint256 selectorPosition = ds\n            .selectorToFacetAndPosition[_selector]\n            .functionSelectorPosition;\n        uint256 lastSelectorPosition = ds\n            .facetFunctionSelectors[_facetAddress]\n            .functionSelectors\n            .length - 1;\n        // if not the same then replace _selector with lastSelector\n        if (selectorPosition != lastSelectorPosition) {\n            bytes4 lastSelector = ds\n                .facetFunctionSelectors[_facetAddress]\n                .functionSelectors[lastSelectorPosition];\n            ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n                selectorPosition\n            ] = lastSelector;\n            ds\n                .selectorToFacetAndPosition[lastSelector]\n                .functionSelectorPosition = uint96(selectorPosition);\n        }\n        // delete the last selector\n        ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n        delete ds.selectorToFacetAndPosition[_selector];\n\n        // if no more selectors for facet address then delete the facet address\n        if (lastSelectorPosition == 0) {\n            // replace facet address with last facet address and delete last facet address\n            uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n            uint256 facetAddressPosition = ds\n                .facetFunctionSelectors[_facetAddress]\n                .facetAddressPosition;\n            if (facetAddressPosition != lastFacetAddressPosition) {\n                address lastFacetAddress = ds.facetAddresses[\n                    lastFacetAddressPosition\n                ];\n                ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n                ds\n                    .facetFunctionSelectors[lastFacetAddress]\n                    .facetAddressPosition = facetAddressPosition;\n            }\n            ds.facetAddresses.pop();\n            delete ds\n                .facetFunctionSelectors[_facetAddress]\n                .facetAddressPosition;\n        }\n    }\n\n    function initializeDiamondCut(\n        address _init,\n        bytes memory _calldata\n    ) internal {\n        if (LibUtil.isZeroAddress(_init)) {\n            if (_calldata.length != 0) {\n                revert InitZeroButCalldataNotEmpty();\n            }\n        } else {\n            if (_calldata.length == 0) {\n                revert CalldataEmptyButInitNotZero();\n            }\n            if (_init != address(this)) {\n                enforceHasContractCode(_init);\n            }\n            // solhint-disable-next-line avoid-low-level-calls\n            (bool success, bytes memory error) = _init.delegatecall(_calldata);\n            if (!success) {\n                if (error.length > 0) {\n                    // bubble up the error\n                    revert(string(error));\n                } else {\n                    revert InitReverted();\n                }\n            }\n        }\n    }\n\n    function enforceHasContractCode(address _contract) internal view {\n        uint256 contractSize;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            contractSize := extcodesize(_contract)\n        }\n        if (contractSize == 0) {\n            revert FacetContainsNoCode();\n        }\n    }\n}\n"
      },
      "src/Libraries/LibAsset.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n///         of assets, including accounting for the native asset `assetId`\n///         conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n    uint256 private constant MAX_UINT = type(uint256).max;\n\n    address internal constant NULL_ADDRESS = address(0);\n\n    /// @dev All native assets use the empty address for their asset id\n    ///      by convention\n\n    address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n    /// @notice Gets the balance of the inheriting contract for the given asset\n    /// @param assetId The asset identifier to get the balance of\n    /// @return Balance held by contracts using this library\n    function getOwnBalance(address assetId) internal view returns (uint256) {\n        return\n            isNativeAsset(assetId)\n                ? address(this).balance\n                : IERC20(assetId).balanceOf(address(this));\n    }\n\n    /// @notice Transfers ether from the inheriting contract to a given\n    ///         recipient\n    /// @param recipient Address to send ether to\n    /// @param amount Amount to send to given recipient\n    function transferNativeAsset(\n        address payable recipient,\n        uint256 amount\n    ) private {\n        if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n        if (amount > address(this).balance)\n            revert InsufficientBalance(amount, address(this).balance);\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, ) = recipient.call{ value: amount }(\"\");\n        if (!success) revert NativeAssetTransferFailed();\n    }\n\n    /// @notice If the current allowance is insufficient, the allowance for a given spender\n    /// is set to MAX_UINT.\n    /// @param assetId Token address to transfer\n    /// @param spender Address to give spend approval to\n    /// @param amount Amount to approve for spending\n    function maxApproveERC20(\n        IERC20 assetId,\n        address spender,\n        uint256 amount\n    ) internal {\n        if (isNativeAsset(address(assetId))) {\n            return;\n        }\n        if (spender == NULL_ADDRESS) {\n            revert NullAddrIsNotAValidSpender();\n        }\n\n        if (assetId.allowance(address(this), spender) < amount) {\n            SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n            SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n        }\n    }\n\n    /// @notice Transfers tokens from the inheriting contract to a given\n    ///         recipient\n    /// @param assetId Token address to transfer\n    /// @param recipient Address to send token to\n    /// @param amount Amount to send to given recipient\n    function transferERC20(\n        address assetId,\n        address recipient,\n        uint256 amount\n    ) private {\n        if (isNativeAsset(assetId)) {\n            revert NullAddrIsNotAnERC20Token();\n        }\n        if (recipient == NULL_ADDRESS) {\n            revert NoTransferToNullAddress();\n        }\n\n        uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n        if (amount > assetBalance) {\n            revert InsufficientBalance(amount, assetBalance);\n        }\n        SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n    }\n\n    /// @notice Transfers tokens from a sender to a given recipient\n    /// @param assetId Token address to transfer\n    /// @param from Address of sender/owner\n    /// @param to Address of recipient/spender\n    /// @param amount Amount to transfer from owner to spender\n    function transferFromERC20(\n        address assetId,\n        address from,\n        address to,\n        uint256 amount\n    ) internal {\n        if (isNativeAsset(assetId)) {\n            revert NullAddrIsNotAnERC20Token();\n        }\n        if (to == NULL_ADDRESS) {\n            revert NoTransferToNullAddress();\n        }\n\n        IERC20 asset = IERC20(assetId);\n        uint256 prevBalance = asset.balanceOf(to);\n        SafeERC20.safeTransferFrom(asset, from, to, amount);\n        if (asset.balanceOf(to) - prevBalance != amount) {\n            revert InvalidAmount();\n        }\n    }\n\n    function depositAsset(address assetId, uint256 amount) internal {\n        if (amount == 0) revert InvalidAmount();\n        if (isNativeAsset(assetId)) {\n            if (msg.value < amount) revert InvalidAmount();\n        } else {\n            uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n            if (balance < amount) revert InsufficientBalance(amount, balance);\n            transferFromERC20(assetId, msg.sender, address(this), amount);\n        }\n    }\n\n    function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n        for (uint256 i = 0; i < swaps.length; ) {\n            LibSwap.SwapData calldata swap = swaps[i];\n            if (swap.requiresDeposit) {\n                depositAsset(swap.sendingAssetId, swap.fromAmount);\n            }\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    /// @notice Determines whether the given assetId is the native asset\n    /// @param assetId The asset identifier to evaluate\n    /// @return Boolean indicating if the asset is the native asset\n    function isNativeAsset(address assetId) internal pure returns (bool) {\n        return assetId == NATIVE_ASSETID;\n    }\n\n    /// @notice Wrapper function to transfer a given asset (native or erc20) to\n    ///         some recipient. Should handle all non-compliant return value\n    ///         tokens as well by using the SafeERC20 contract by open zeppelin.\n    /// @param assetId Asset id for transfer (address(0) for native asset,\n    ///                token address for erc20s)\n    /// @param recipient Address to send asset to\n    /// @param amount Amount to send to given recipient\n    function transferAsset(\n        address assetId,\n        address payable recipient,\n        uint256 amount\n    ) internal {\n        isNativeAsset(assetId)\n            ? transferNativeAsset(recipient, amount)\n            : transferERC20(assetId, recipient, amount);\n    }\n\n    /// @dev Checks whether the given address is a contract and contains code\n    function isContract(address _contractAddr) internal view returns (bool) {\n        uint256 size;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            size := extcodesize(_contractAddr)\n        }\n        return size > 0;\n    }\n}\n"
      },
      "src/Libraries/LibSwap.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n    struct SwapData {\n        address callTo;\n        address approveTo;\n        address sendingAssetId;\n        address receivingAssetId;\n        uint256 fromAmount;\n        bytes callData;\n        bool requiresDeposit;\n    }\n\n    event AssetSwapped(\n        bytes32 transactionId,\n        address dex,\n        address fromAssetId,\n        address toAssetId,\n        uint256 fromAmount,\n        uint256 toAmount,\n        uint256 timestamp\n    );\n\n    function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n        if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n        uint256 fromAmount = _swap.fromAmount;\n        if (fromAmount == 0) revert NoSwapFromZeroBalance();\n        uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n            ? _swap.fromAmount\n            : 0;\n        uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n            _swap.sendingAssetId\n        );\n        uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n            _swap.receivingAssetId\n        );\n\n        if (nativeValue == 0) {\n            LibAsset.maxApproveERC20(\n                IERC20(_swap.sendingAssetId),\n                _swap.approveTo,\n                _swap.fromAmount\n            );\n        }\n\n        if (initialSendingAssetBalance < _swap.fromAmount) {\n            revert InsufficientBalance(\n                _swap.fromAmount,\n                initialSendingAssetBalance\n            );\n        }\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory res) = _swap.callTo.call{\n            value: nativeValue\n        }(_swap.callData);\n        if (!success) {\n            string memory reason = LibUtil.getRevertMsg(res);\n            revert(reason);\n        }\n\n        uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n        emit AssetSwapped(\n            transactionId,\n            _swap.callTo,\n            _swap.sendingAssetId,\n            _swap.receivingAssetId,\n            _swap.fromAmount,\n            newBalance > initialReceivingAssetBalance\n                ? newBalance - initialReceivingAssetBalance\n                : newBalance,\n            block.timestamp\n        );\n    }\n}\n"
      },
      "src/Helpers/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n    /// Storage ///\n\n    bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n    /// Types ///\n\n    struct ReentrancyStorage {\n        uint256 status;\n    }\n\n    /// Errors ///\n\n    error ReentrancyError();\n\n    /// Constants ///\n\n    uint256 private constant _NOT_ENTERED = 0;\n    uint256 private constant _ENTERED = 1;\n\n    /// Modifiers ///\n\n    modifier nonReentrant() {\n        ReentrancyStorage storage s = reentrancyStorage();\n        if (s.status == _ENTERED) revert ReentrancyError();\n        s.status = _ENTERED;\n        _;\n        s.status = _NOT_ENTERED;\n    }\n\n    /// Private Methods ///\n\n    /// @dev fetch local storage\n    function reentrancyStorage()\n        private\n        pure\n        returns (ReentrancyStorage storage data)\n    {\n        bytes32 position = NAMESPACE;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            data.slot := position\n        }\n    }\n}\n"
      },
      "src/Helpers/SwapperV2.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n    /// Types ///\n\n    /// @dev only used to get around \"Stack Too Deep\" errors\n    struct ReserveData {\n        bytes32 transactionId;\n        address payable leftoverReceiver;\n        uint256 nativeReserve;\n    }\n\n    /// Modifiers ///\n\n    /// @dev Sends any leftover balances back to the user\n    /// @notice Sends any leftover balances to the user\n    /// @param _swaps Swap data array\n    /// @param _leftoverReceiver Address to send leftover tokens to\n    /// @param _initialBalances Array of initial token balances\n    modifier noLeftovers(\n        LibSwap.SwapData[] calldata _swaps,\n        address payable _leftoverReceiver,\n        uint256[] memory _initialBalances\n    ) {\n        uint256 numSwaps = _swaps.length;\n        if (numSwaps != 1) {\n            address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n            uint256 curBalance;\n\n            _;\n\n            for (uint256 i = 0; i < numSwaps - 1; ) {\n                address curAsset = _swaps[i].receivingAssetId;\n                // Handle multi-to-one swaps\n                if (curAsset != finalAsset) {\n                    curBalance =\n                        LibAsset.getOwnBalance(curAsset) -\n                        _initialBalances[i];\n                    if (curBalance > 0) {\n                        LibAsset.transferAsset(\n                            curAsset,\n                            _leftoverReceiver,\n                            curBalance\n                        );\n                    }\n                }\n                unchecked {\n                    ++i;\n                }\n            }\n        } else {\n            _;\n        }\n    }\n\n    /// @dev Sends any leftover balances back to the user reserving native tokens\n    /// @notice Sends any leftover balances to the user\n    /// @param _swaps Swap data array\n    /// @param _leftoverReceiver Address to send leftover tokens to\n    /// @param _initialBalances Array of initial token balances\n    modifier noLeftoversReserve(\n        LibSwap.SwapData[] calldata _swaps,\n        address payable _leftoverReceiver,\n        uint256[] memory _initialBalances,\n        uint256 _nativeReserve\n    ) {\n        uint256 numSwaps = _swaps.length;\n        if (numSwaps != 1) {\n            address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n            uint256 curBalance;\n\n            _;\n\n            for (uint256 i = 0; i < numSwaps - 1; ) {\n                address curAsset = _swaps[i].receivingAssetId;\n                // Handle multi-to-one swaps\n                if (curAsset != finalAsset) {\n                    curBalance =\n                        LibAsset.getOwnBalance(curAsset) -\n                        _initialBalances[i];\n                    uint256 reserve = LibAsset.isNativeAsset(curAsset)\n                        ? _nativeReserve\n                        : 0;\n                    if (curBalance > 0) {\n                        LibAsset.transferAsset(\n                            curAsset,\n                            _leftoverReceiver,\n                            curBalance - reserve\n                        );\n                    }\n                }\n                unchecked {\n                    ++i;\n                }\n            }\n        } else {\n            _;\n        }\n    }\n\n    /// @dev Refunds any excess native asset sent to the contract after the main function\n    /// @notice Refunds any excess native asset sent to the contract after the main function\n    /// @param _refundReceiver Address to send refunds to\n    modifier refundExcessNative(address payable _refundReceiver) {\n        uint256 initialBalance = address(this).balance - msg.value;\n        _;\n        uint256 finalBalance = address(this).balance;\n\n        if (finalBalance > initialBalance) {\n            LibAsset.transferAsset(\n                LibAsset.NATIVE_ASSETID,\n                _refundReceiver,\n                finalBalance - initialBalance\n            );\n        }\n    }\n\n    /// Internal Methods ///\n\n    /// @dev Deposits value, executes swaps, and performs minimum amount check\n    /// @param _transactionId the transaction id associated with the operation\n    /// @param _minAmount the minimum amount of the final asset to receive\n    /// @param _swaps Array of data used to execute swaps\n    /// @param _leftoverReceiver The address to send leftover funds to\n    /// @return uint256 result of the swap\n    function _depositAndSwap(\n        bytes32 _transactionId,\n        uint256 _minAmount,\n        LibSwap.SwapData[] calldata _swaps,\n        address payable _leftoverReceiver\n    ) internal returns (uint256) {\n        uint256 numSwaps = _swaps.length;\n\n        if (numSwaps == 0) {\n            revert NoSwapDataProvided();\n        }\n\n        address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n        uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n        if (LibAsset.isNativeAsset(finalTokenId)) {\n            initialBalance -= msg.value;\n        }\n\n        uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n        LibAsset.depositAssets(_swaps);\n        _executeSwaps(\n            _transactionId,\n            _swaps,\n            _leftoverReceiver,\n            initialBalances\n        );\n\n        uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n            initialBalance;\n\n        if (newBalance < _minAmount) {\n            revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n        }\n\n        return newBalance;\n    }\n\n    /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n    /// @param _transactionId the transaction id associated with the operation\n    /// @param _minAmount the minimum amount of the final asset to receive\n    /// @param _swaps Array of data used to execute swaps\n    /// @param _leftoverReceiver The address to send leftover funds to\n    /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n    function _depositAndSwap(\n        bytes32 _transactionId,\n        uint256 _minAmount,\n        LibSwap.SwapData[] calldata _swaps,\n        address payable _leftoverReceiver,\n        uint256 _nativeReserve\n    ) internal returns (uint256) {\n        uint256 numSwaps = _swaps.length;\n\n        if (numSwaps == 0) {\n            revert NoSwapDataProvided();\n        }\n\n        address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n        uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n        if (LibAsset.isNativeAsset(finalTokenId)) {\n            initialBalance -= msg.value;\n        }\n\n        uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n        LibAsset.depositAssets(_swaps);\n        ReserveData memory rd = ReserveData(\n            _transactionId,\n            _leftoverReceiver,\n            _nativeReserve\n        );\n        _executeSwaps(rd, _swaps, initialBalances);\n\n        uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n            initialBalance;\n\n        if (LibAsset.isNativeAsset(finalTokenId)) {\n            newBalance -= _nativeReserve;\n        }\n\n        if (newBalance < _minAmount) {\n            revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n        }\n\n        return newBalance;\n    }\n\n    /// Private Methods ///\n\n    /// @dev Executes swaps and checks that DEXs used are in the allowList\n    /// @param _transactionId the transaction id associated with the operation\n    /// @param _swaps Array of data used to execute swaps\n    /// @param _leftoverReceiver Address to send leftover tokens to\n    /// @param _initialBalances Array of initial balances\n    function _executeSwaps(\n        bytes32 _transactionId,\n        LibSwap.SwapData[] calldata _swaps,\n        address payable _leftoverReceiver,\n        uint256[] memory _initialBalances\n    ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n        uint256 numSwaps = _swaps.length;\n        for (uint256 i = 0; i < numSwaps; ) {\n            LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n            if (\n                !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n                    LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n                    LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n                    LibAllowList.selectorIsAllowed(\n                        bytes4(currentSwap.callData[:4])\n                    ))\n            ) revert ContractCallNotAllowed();\n\n            LibSwap.swap(_transactionId, currentSwap);\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /// @dev Executes swaps and checks that DEXs used are in the allowList\n    /// @param _reserveData Data passed used to reserve native tokens\n    /// @param _swaps Array of data used to execute swaps\n    function _executeSwaps(\n        ReserveData memory _reserveData,\n        LibSwap.SwapData[] calldata _swaps,\n        uint256[] memory _initialBalances\n    )\n        internal\n        noLeftoversReserve(\n            _swaps,\n            _reserveData.leftoverReceiver,\n            _initialBalances,\n            _reserveData.nativeReserve\n        )\n    {\n        uint256 numSwaps = _swaps.length;\n        for (uint256 i = 0; i < numSwaps; ) {\n            LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n            if (\n                !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n                    LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n                    LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n                    LibAllowList.selectorIsAllowed(\n                        bytes4(currentSwap.callData[:4])\n                    ))\n            ) revert ContractCallNotAllowed();\n\n            LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /// @dev Fetches balances of tokens to be swapped before swapping.\n    /// @param _swaps Array of data used to execute swaps\n    /// @return uint256[] Array of token balances.\n    function _fetchBalances(\n        LibSwap.SwapData[] calldata _swaps\n    ) private view returns (uint256[] memory) {\n        uint256 numSwaps = _swaps.length;\n        uint256[] memory balances = new uint256[](numSwaps);\n        address asset;\n        for (uint256 i = 0; i < numSwaps; ) {\n            asset = _swaps[i].receivingAssetId;\n            balances[i] = LibAsset.getOwnBalance(asset);\n\n            if (LibAsset.isNativeAsset(asset)) {\n                balances[i] -= msg.value;\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n\n        return balances;\n    }\n}\n"
      },
      "src/Helpers/Validatable.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n    modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n        if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n            revert InvalidReceiver();\n        }\n        if (_bridgeData.minAmount == 0) {\n            revert InvalidAmount();\n        }\n        if (_bridgeData.destinationChainId == block.chainid) {\n            revert CannotBridgeToSameNetwork();\n        }\n        _;\n    }\n\n    modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n        if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n            revert NativeAssetNotSupported();\n        }\n        _;\n    }\n\n    modifier onlyAllowSourceToken(\n        ILiFi.BridgeData memory _bridgeData,\n        address _token\n    ) {\n        if (_bridgeData.sendingAssetId != _token) {\n            revert InvalidSendingToken();\n        }\n        _;\n    }\n\n    modifier onlyAllowDestinationChain(\n        ILiFi.BridgeData memory _bridgeData,\n        uint256 _chainId\n    ) {\n        if (_bridgeData.destinationChainId != _chainId) {\n            revert InvalidDestinationChain();\n        }\n        _;\n    }\n\n    modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n        if (!_bridgeData.hasSourceSwaps) {\n            revert InformationMismatch();\n        }\n        _;\n    }\n\n    modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n        if (_bridgeData.hasSourceSwaps) {\n            revert InformationMismatch();\n        }\n        _;\n    }\n\n    modifier doesNotContainDestinationCalls(\n        ILiFi.BridgeData memory _bridgeData\n    ) {\n        if (_bridgeData.hasDestinationCall) {\n            revert InformationMismatch();\n        }\n        _;\n    }\n}\n"
      },
      "src/Interfaces/IMayan.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IMayan {\n    struct RelayerFees {\n        uint64 swapFee;\n        uint64 redeemFee;\n        uint64 refundFee;\n    }\n\n    struct Recepient {\n        bytes32 mayanAddr;\n        uint16 mayanChainId;\n        bytes32 auctionAddr;\n        bytes32 destAddr;\n        uint16 destChainId;\n        bytes32 referrer;\n        bytes32 refundAddr;\n    }\n\n    struct Criteria {\n        uint256 transferDeadline;\n        uint64 swapDeadline;\n        uint64 amountOutMin;\n        bool unwrap;\n        uint64 gasDrop;\n        bytes customPayload;\n    }\n\n    function swap(\n        RelayerFees memory relayerFees,\n        Recepient memory recipient,\n        bytes32 tokenOutAddr,\n        uint16 tokenOutChainId,\n        Criteria memory criteria,\n        address tokenIn,\n        uint256 amountIn\n    ) external payable returns (uint64 sequence);\n\n    function wrapAndSwapETH(\n        RelayerFees memory relayerFees,\n        Recepient memory recipient,\n        bytes32 tokenOutAddr,\n        uint16 tokenOutChainId,\n        Criteria memory criteria\n    ) external payable returns (uint64 sequence);\n}\n"
      },
      "src/Errors/GenericErrors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n"
      },
      "src/Interfaces/IDiamondCut.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n    enum FacetCutAction {\n        Add,\n        Replace,\n        Remove\n    }\n    // Add=0, Replace=1, Remove=2\n\n    struct FacetCut {\n        address facetAddress;\n        FacetCutAction action;\n        bytes4[] functionSelectors;\n    }\n\n    /// @notice Add/replace/remove any number of functions and optionally execute\n    ///         a function with delegatecall\n    /// @param _diamondCut Contains the facet addresses and function selectors\n    /// @param _init The address of the contract or facet to execute _calldata\n    /// @param _calldata A function call, including function selector and arguments\n    ///                  _calldata is executed with delegatecall on _init\n    function diamondCut(\n        FacetCut[] calldata _diamondCut,\n        address _init,\n        bytes calldata _calldata\n    ) external;\n\n    event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n"
      },
      "src/Libraries/LibUtil.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n    using LibBytes for bytes;\n\n    function getRevertMsg(\n        bytes memory _res\n    ) internal pure returns (string memory) {\n        // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n        if (_res.length < 68) return \"Transaction reverted silently\";\n        bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n        return abi.decode(revertData, (string)); // All that remains is the revert string\n    }\n\n    /// @notice Determines whether the given address is the zero address\n    /// @param addr The address to verify\n    /// @return Boolean indicating if the address is the zero address\n    function isZeroAddress(address addr) internal pure returns (bool) {\n        return addr == address(0);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n     * 0 before setting it to a non-zero value.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "src/Libraries/LibAllowList.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n    /// Storage ///\n    bytes32 internal constant NAMESPACE =\n        keccak256(\"com.lifi.library.allow.list\");\n\n    struct AllowListStorage {\n        mapping(address => bool) allowlist;\n        mapping(bytes4 => bool) selectorAllowList;\n        address[] contracts;\n    }\n\n    /// @dev Adds a contract address to the allow list\n    /// @param _contract the contract address to add\n    function addAllowedContract(address _contract) internal {\n        _checkAddress(_contract);\n\n        AllowListStorage storage als = _getStorage();\n\n        if (als.allowlist[_contract]) return;\n\n        als.allowlist[_contract] = true;\n        als.contracts.push(_contract);\n    }\n\n    /// @dev Checks whether a contract address has been added to the allow list\n    /// @param _contract the contract address to check\n    function contractIsAllowed(\n        address _contract\n    ) internal view returns (bool) {\n        return _getStorage().allowlist[_contract];\n    }\n\n    /// @dev Remove a contract address from the allow list\n    /// @param _contract the contract address to remove\n    function removeAllowedContract(address _contract) internal {\n        AllowListStorage storage als = _getStorage();\n\n        if (!als.allowlist[_contract]) {\n            return;\n        }\n\n        als.allowlist[_contract] = false;\n\n        uint256 length = als.contracts.length;\n        // Find the contract in the list\n        for (uint256 i = 0; i < length; i++) {\n            if (als.contracts[i] == _contract) {\n                // Move the last element into the place to delete\n                als.contracts[i] = als.contracts[length - 1];\n                // Remove the last element\n                als.contracts.pop();\n                break;\n            }\n        }\n    }\n\n    /// @dev Fetch contract addresses from the allow list\n    function getAllowedContracts() internal view returns (address[] memory) {\n        return _getStorage().contracts;\n    }\n\n    /// @dev Add a selector to the allow list\n    /// @param _selector the selector to add\n    function addAllowedSelector(bytes4 _selector) internal {\n        _getStorage().selectorAllowList[_selector] = true;\n    }\n\n    /// @dev Removes a selector from the allow list\n    /// @param _selector the selector to remove\n    function removeAllowedSelector(bytes4 _selector) internal {\n        _getStorage().selectorAllowList[_selector] = false;\n    }\n\n    /// @dev Returns if selector has been added to the allow list\n    /// @param _selector the selector to check\n    function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n        return _getStorage().selectorAllowList[_selector];\n    }\n\n    /// @dev Fetch local storage struct\n    function _getStorage()\n        internal\n        pure\n        returns (AllowListStorage storage als)\n    {\n        bytes32 position = NAMESPACE;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            als.slot := position\n        }\n    }\n\n    /// @dev Contains business logic for validating a contract address.\n    /// @param _contract address of the dex to check\n    function _checkAddress(address _contract) private view {\n        if (_contract == address(0)) revert InvalidContract();\n\n        if (_contract.code.length == 0) revert InvalidContract();\n    }\n}\n"
      },
      "src/Libraries/LibBytes.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n    // solhint-disable no-inline-assembly\n\n    // LibBytes specific errors\n    error SliceOverflow();\n    error SliceOutOfBounds();\n    error AddressOutOfBounds();\n\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n    // -------------------------\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    ) internal pure returns (bytes memory) {\n        if (_length + 31 < _length) revert SliceOverflow();\n        if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n        bytes memory tempBytes;\n\n        assembly {\n            switch iszero(_length)\n            case 0 {\n                // Get a location of some free memory and store it in tempBytes as\n                // Solidity does for memory variables.\n                tempBytes := mload(0x40)\n\n                // The first word of the slice result is potentially a partial\n                // word read from the original array. To read it, we calculate\n                // the length of that partial word and start copying that many\n                // bytes into the array. The first word we copy will start with\n                // data we don't care about, but the last `lengthmod` bytes will\n                // land at the beginning of the contents of the new array. When\n                // we're done copying, we overwrite the full first word with\n                // the actual length of the slice.\n                let lengthmod := and(_length, 31)\n\n                // The multiplication in the next line is necessary\n                // because when slicing multiples of 32 bytes (lengthmod == 0)\n                // the following copy loop was copying the origin's length\n                // and then ending prematurely not copying everything it should.\n                let mc := add(\n                    add(tempBytes, lengthmod),\n                    mul(0x20, iszero(lengthmod))\n                )\n                let end := add(mc, _length)\n\n                for {\n                    // The multiplication in the next line has the same exact purpose\n                    // as the one above.\n                    let cc := add(\n                        add(\n                            add(_bytes, lengthmod),\n                            mul(0x20, iszero(lengthmod))\n                        ),\n                        _start\n                    )\n                } lt(mc, end) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    mstore(mc, mload(cc))\n                }\n\n                mstore(tempBytes, _length)\n\n                //update free-memory pointer\n                //allocating the array padded to 32 bytes like the compiler does now\n                mstore(0x40, and(add(mc, 31), not(31)))\n            }\n            //if we want a zero-length slice let's just return a zero-length array\n            default {\n                tempBytes := mload(0x40)\n                //zero out the 32 bytes slice we are about to return\n                //we need to do it because Solidity does not garbage collect\n                mstore(tempBytes, 0)\n\n                mstore(0x40, add(tempBytes, 0x20))\n            }\n        }\n\n        return tempBytes;\n    }\n\n    function toAddress(\n        bytes memory _bytes,\n        uint256 _start\n    ) internal pure returns (address) {\n        if (_bytes.length < _start + 20) {\n            revert AddressOutOfBounds();\n        }\n        address tempAddress;\n\n        assembly {\n            tempAddress := div(\n                mload(add(add(_bytes, 0x20), _start)),\n                0x1000000000000000000000000\n            )\n        }\n\n        return tempAddress;\n    }\n\n    /// Copied from OpenZeppelin's `Strings.sol` utility library.\n    /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n    function toHexString(\n        uint256 value,\n        uint256 length\n    ) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/",
        "@uniswap/=node_modules/@uniswap/",
        "eth-gas-reporter/=node_modules/eth-gas-reporter/",
        "hardhat/=node_modules/hardhat/",
        "hardhat-deploy/=node_modules/hardhat-deploy/",
        "@openzeppelin/=lib/openzeppelin-contracts/",
        "celer-network/=lib/sgn-v2-contracts/",
        "create3-factory/=lib/create3-factory/src/",
        "solmate/=lib/solmate/src/",
        "ds-test/=lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "lifi/=src/",
        "test/=test/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 1000000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs"
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "viaIR": false,
      "libraries": {}
    }
  }}