{
  "language": "Solidity",
  "sources": {
    "src/bridges/facets/StargateFacet.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.4;\r\n\r\nimport {IStargateRouter} from \"../interfaces/IStargateRouter.sol\";\r\nimport {IStargateReceiver} from \"../interfaces/IStargateReceiver.sol\";\r\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\r\nimport {ReentrancyGuard} from \"../../common/helpers/DiamondReentrancyGuard.sol\";\r\nimport {CannotBridgeToSameNetwork, InvalidAmount, InvalidConfig} from \"../errors/GenericErrors.sol\";\r\nimport {SenderNotStargateRouter, NoMsgValueForCrossChainMessage, StargateRouterAddressZero, InvalidSourcePoolId, InvalidDestinationPoolId} from \"../errors/StargateErrors.sol\";\r\nimport {LibDiamond} from \"../libs/LibDiamond.sol\";\r\n\r\n/// @title StargateFacet\r\n/// @author Luke Wickens <luke@pillarproject.io>\r\n/// @notice Stargate/LayerZero intergration for bridging tokens\r\n\r\ncontract StargateFacet is IStargateReceiver, ReentrancyGuard {\r\n    using SafeERC20 for IERC20;\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    /////////////////////////// Events ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n    event SGInitialized(address stargate, uint16 chainId);\r\n    event SGTransferStarted(\r\n        string bridgeUsed,\r\n        address fromToken,\r\n        address toToken,\r\n        address from,\r\n        address to,\r\n        uint256 amount,\r\n        uint16 chainIdTo\r\n    );\r\n    event SGReceivedOnDestination(address token, uint256 amount);\r\n    event SGUpdatedRouter(address newAddress);\r\n    event SGUpdatedSlippageTolerance(uint256 newSlippage);\r\n    event SGAddedPool(uint16 chainId, address token, uint16 poolId);\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////////// Storage ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    bytes32 internal constant NAMESPACE =\r\n        keccak256(\"io.etherspot.facets.stargate\");\r\n    struct Storage {\r\n        address stargateRouter;\r\n        uint16 chainId;\r\n        uint256 dstGas;\r\n        uint256 slippage;\r\n        mapping(uint16 => mapping(address => uint16)) poolIds;\r\n    }\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////////// Structs ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    struct StargateData {\r\n        uint256 qty;\r\n        address fromToken;\r\n        address toToken;\r\n        uint16 dstChainId;\r\n        address to;\r\n        address destStargateComposed;\r\n    }\r\n\r\n    /// @notice initializes state variables for the Stargate facet\r\n    /// @param _stargateRouter - address of the Stargate router contract\r\n    /// @param _chainId - current chain id\r\n    function sgInitialize(address _stargateRouter, uint16 _chainId) external {\r\n        if (_stargateRouter == address(0)) revert InvalidConfig();\r\n        LibDiamond.enforceIsContractOwner();\r\n        Storage storage s = getStorage();\r\n        s.stargateRouter = address(_stargateRouter);\r\n        s.chainId = _chainId;\r\n        s.slippage = 50; // equates to 0.5%\r\n        // Adding pre-existing pools => USDC: 1, USDT: 2, BUSD: 5\r\n        sgAddPool(1, 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, 1);\r\n        sgAddPool(1, 0xdAC17F958D2ee523a2206206994597C13D831ec7, 2);\r\n        sgAddPool(2, 0x55d398326f99059fF775485246999027B3197955, 2);\r\n        sgAddPool(2, 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56, 5);\r\n        sgAddPool(6, 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E, 1);\r\n        sgAddPool(6, 0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7, 2);\r\n        sgAddPool(9, 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174, 1);\r\n        sgAddPool(9, 0xc2132D05D31c914a87C6611C10748AEb04B58e8F, 2);\r\n        sgAddPool(10, 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8, 1);\r\n        sgAddPool(10, 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9, 2);\r\n        sgAddPool(11, 0x7F5c764cBc14f9669B88837ca1490cCa17c31607, 1);\r\n        sgAddPool(12, 0x04068DA6C83AFCFA0e13ba15A6696662335D5B75, 1);\r\n        emit SGInitialized(_stargateRouter, _chainId);\r\n    }\r\n\r\n    /// @notice initializes state variables for the stargate facet\r\n    /// @param _sgData - struct containing information required to execute bridge\r\n    function sgBridgeTokens(StargateData memory _sgData)\r\n        external\r\n        payable\r\n        nonReentrant\r\n    {\r\n        // if (msg.value <= 0) revert NoMsgValueForCrossChainMessage();\r\n        if (_sgData.qty <= 0) revert InvalidAmount();\r\n        if (\r\n            _sgData.fromToken == address(0) ||\r\n            _sgData.toToken == address(0) ||\r\n            _sgData.to == address(0) ||\r\n            _sgData.destStargateComposed == address(0)\r\n        ) revert InvalidConfig();\r\n\r\n        // access storage\r\n        Storage storage s = getStorage();\r\n\r\n        // check pool ids are valid\r\n        uint16 srcPoolId = sgRetrievePoolId(s.chainId, _sgData.fromToken);\r\n        if (srcPoolId == 0) revert InvalidSourcePoolId();\r\n        uint16 dstPoolId = sgRetrievePoolId(\r\n            _sgData.dstChainId,\r\n            _sgData.toToken\r\n        );\r\n\r\n        // calculate cross chain fees\r\n        uint256 fees = sgCalculateFees(\r\n            _sgData.dstChainId,\r\n            _sgData.to,\r\n            s.stargateRouter\r\n        );\r\n\r\n        // calculate slippage\r\n        uint256 minAmountOut = sgMinAmountOut(_sgData.qty);\r\n\r\n        // encode sgReceive implemented\r\n        bytes memory destination = abi.encodePacked(\r\n            _sgData.destStargateComposed\r\n        );\r\n\r\n        // encode payload data to send to destination contract, which it will handle with sgReceive()\r\n        bytes memory payload = abi.encode(_sgData.to);\r\n\r\n        // this contract calls stargate swap()\r\n        IERC20(_sgData.fromToken).safeTransferFrom(\r\n            msg.sender,\r\n            address(this),\r\n            _sgData.qty\r\n        );\r\n\r\n        IERC20(_sgData.fromToken).safeApprove(\r\n            address(s.stargateRouter),\r\n            _sgData.qty\r\n        );\r\n\r\n        // Stargate's Router.swap() function sends the tokens to the destination chain.\r\n        IStargateRouter(s.stargateRouter).swap{value: fees}(\r\n            _sgData.dstChainId, // the destination chain id\r\n            srcPoolId, // the source Stargate poolId\r\n            dstPoolId, // the destination Stargate poolId\r\n            payable(msg.sender), // refund adddress. if msg.sender pays too much gas, return extra eth\r\n            _sgData.qty, // total tokens to send to destination chain\r\n            minAmountOut, // min amount allowed out\r\n            IStargateRouter.lzTxObj(200000, 0, \"0x\"), // default lzTxObj\r\n            destination, // destination address, the sgReceive() implementer\r\n            payload // bytes payload\r\n        );\r\n\r\n        emit SGTransferStarted(\r\n            \"stargate\",\r\n            _sgData.fromToken,\r\n            _sgData.toToken,\r\n            msg.sender,\r\n            _sgData.to,\r\n            _sgData.qty,\r\n            _sgData.dstChainId\r\n        );\r\n    }\r\n\r\n    /// @notice required to receive tokens on destination chain\r\n    /// @param _chainId The remote chainId sending the tokens\r\n    /// @param _srcAddress The remote Bridge address\r\n    /// @param _nonce The message ordering nonce\r\n    /// @param _token The token contract on the local chain\r\n    /// @param amountLD The qty of local _token contract tokens\r\n    /// @param _payload The bytes containing the toAddress\r\n    function sgReceive(\r\n        uint16 _chainId,\r\n        bytes memory _srcAddress,\r\n        uint256 _nonce,\r\n        address _token,\r\n        uint256 amountLD,\r\n        bytes memory _payload\r\n    ) external override {\r\n        Storage storage s = getStorage();\r\n        if (msg.sender != address(s.stargateRouter))\r\n            revert SenderNotStargateRouter();\r\n\r\n        address _toAddr = abi.decode(_payload, (address));\r\n        IERC20(_token).transfer(_toAddr, amountLD);\r\n        emit SGReceivedOnDestination(_token, amountLD);\r\n    }\r\n\r\n    /// @notice Calculates cross chain fee\r\n    /// @param _destChain Destination chain id\r\n    /// @param _receiver Receiver on destination chain\r\n    /// @param _router Address of stargate router\r\n    function sgCalculateFees(\r\n        uint16 _destChain,\r\n        address _receiver,\r\n        address _router\r\n    ) public view returns (uint256) {\r\n        (uint256 nativeFee, ) = IStargateRouter(_router).quoteLayerZeroFee(\r\n            _destChain, // destination chain id\r\n            1, // 1 = swap\r\n            abi.encodePacked(_receiver), // receiver on destination chain\r\n            \"0x\", // payload, using abi.encode()\r\n            IStargateRouter.lzTxObj(200000, 0, \"0x\")\r\n        );\r\n        return nativeFee;\r\n    }\r\n\r\n    /// @notice Calculates the minimum amount out using slippage tolerance\r\n    /// @param _amount Transfer amount\r\n    function sgMinAmountOut(uint256 _amount) public view returns (uint256) {\r\n        Storage storage s = getStorage();\r\n        // equates to 0.5% slippage\r\n        return (_amount * (10000 - s.slippage)) / (10000);\r\n    }\r\n\r\n    /// @notice Updates stargate router address for deployed chain\r\n    /// @param _newAddress Address of the new router\r\n    function sgUpdateRouter(address _newAddress) external {\r\n        LibDiamond.enforceIsContractOwner();\r\n        if (_newAddress == address(0)) revert StargateRouterAddressZero();\r\n        Storage storage s = getStorage();\r\n        s.stargateRouter = address(_newAddress);\r\n        emit SGUpdatedRouter(_newAddress);\r\n    }\r\n\r\n    /// @notice Updates slippage tolerance amount\r\n    /// @param _newSlippage New slippage amount\r\n    function sgUpdateSlippageTolerance(uint256 _newSlippage) external {\r\n        LibDiamond.enforceIsContractOwner();\r\n        Storage storage s = getStorage();\r\n        s.slippage = _newSlippage;\r\n        emit SGUpdatedSlippageTolerance(_newSlippage);\r\n    }\r\n\r\n    /// @notice Adds a new pool for a specific token and chain\r\n    /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\r\n    /// @param _token Address of token\r\n    /// @param _poolId Pool id (check stargate pool ids docs)\r\n    function sgAddPool(\r\n        uint16 _chainId,\r\n        address _token,\r\n        uint16 _poolId\r\n    ) public {\r\n        LibDiamond.enforceIsContractOwner();\r\n        Storage storage s = getStorage();\r\n        s.poolIds[_chainId][_token] = _poolId;\r\n        emit SGAddedPool(_chainId, _token, _poolId);\r\n    }\r\n\r\n    /// @notice Checks for a valid token pool on specific chain\r\n    /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\r\n    /// @param _token Address of token\r\n    /// @param _poolId Pool id (check stargate pool ids docs)\r\n    function sgCheckPoolId(\r\n        uint16 _chainId,\r\n        address _token,\r\n        uint16 _poolId\r\n    ) external view returns (bool) {\r\n        Storage storage s = getStorage();\r\n        return s.poolIds[_chainId][_token] == _poolId ? true : false;\r\n    }\r\n\r\n    /// @notice Retrieves pool id for a token on a specified chain\r\n    /// @param _chainId Chain id of new pool (NOT actual chain id - check stargate pool ids docs)\r\n    /// @param _token Address of token\r\n    function sgRetrievePoolId(uint16 _chainId, address _token)\r\n        public\r\n        view\r\n        returns (uint16)\r\n    {\r\n        Storage storage s = getStorage();\r\n        return s.poolIds[_chainId][_token];\r\n    }\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////// Private Functions /////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    /// @dev fetch local storage\r\n    function getStorage() private pure returns (Storage storage s) {\r\n        bytes32 namespace = NAMESPACE;\r\n        // solhint-disable-next-line no-inline-assembly\r\n        assembly {\r\n            s.slot := namespace\r\n        }\r\n    }\r\n}\r\n"
    },
    "src/bridges/interfaces/IStargateRouter.sol": {
      "content": "// SPDX-License-Identifier:MIT\r\n\r\npragma solidity 0.8.4;\r\npragma abicoder v2;\r\n\r\ninterface IStargateRouter {\r\n    struct lzTxObj {\r\n        uint256 dstGasForCall;\r\n        uint256 dstNativeAmount;\r\n        bytes dstNativeAddr;\r\n    }\r\n\r\n    function addLiquidity(\r\n        uint256 _poolId,\r\n        uint256 _amountLD,\r\n        address _to\r\n    ) external;\r\n\r\n    function swap(\r\n        uint16 _dstChainId,\r\n        uint256 _srcPoolId,\r\n        uint256 _dstPoolId,\r\n        address payable _refundAddress,\r\n        uint256 _amountLD,\r\n        uint256 _minAmountLD,\r\n        lzTxObj memory _lzTxParams,\r\n        bytes calldata _to,\r\n        bytes calldata _payload\r\n    ) external payable;\r\n\r\n    function redeemRemote(\r\n        uint16 _dstChainId,\r\n        uint256 _srcPoolId,\r\n        uint256 _dstPoolId,\r\n        address payable _refundAddress,\r\n        uint256 _amountLP,\r\n        uint256 _minAmountLD,\r\n        bytes calldata _to,\r\n        lzTxObj memory _lzTxParams\r\n    ) external payable;\r\n\r\n    function instantRedeemLocal(\r\n        uint16 _srcPoolId,\r\n        uint256 _amountLP,\r\n        address _to\r\n    ) external returns (uint256);\r\n\r\n    function redeemLocal(\r\n        uint16 _dstChainId,\r\n        uint256 _srcPoolId,\r\n        uint256 _dstPoolId,\r\n        address payable _refundAddress,\r\n        uint256 _amountLP,\r\n        bytes calldata _to,\r\n        lzTxObj memory _lzTxParams\r\n    ) external payable;\r\n\r\n    function sendCredits(\r\n        uint16 _dstChainId,\r\n        uint256 _srcPoolId,\r\n        uint256 _dstPoolId,\r\n        address payable _refundAddress\r\n    ) external payable;\r\n\r\n    function quoteLayerZeroFee(\r\n        uint16 _dstChainId,\r\n        uint8 _functionType,\r\n        bytes calldata _toAddress,\r\n        bytes calldata _transferAndCallPayload,\r\n        lzTxObj memory _lzTxParams\r\n    ) external view returns (uint256, uint256);\r\n}\r\n"
    },
    "src/bridges/interfaces/IStargateReceiver.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\n\r\npragma solidity 0.8.4;\r\n\r\ninterface IStargateReceiver {\r\n    function sgReceive(\r\n        uint16 _srcChainId, // the remote chainId sending the tokens\r\n        bytes memory _srcAddress, // the remote Bridge address\r\n        uint256 _nonce,\r\n        address _token, // the token contract on the local chain\r\n        uint256 amountLD, // the qty of local _token contract tokens\r\n        bytes memory payload\r\n    ) external;\r\n}\r\n"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.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    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) 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(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) 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    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\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        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
    },
    "src/common/helpers/DiamondReentrancyGuard.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.4;\r\n\r\n/// @title Reentrancy Guard\r\n/// @notice Abstract contract to provide protection against reentrancy\r\nabstract contract ReentrancyGuard {\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////////// Storage ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    bytes32 private constant NAMESPACE =\r\n        keccak256(\"io.etherspot.helpers.reentrancyguard\");\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////////// Structs ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    struct ReentrancyStorage {\r\n        uint256 status;\r\n    }\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////////// Errors ////////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    error ReentrancyError();\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ///////////////////////// Constants //////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    uint256 private constant _NOT_ENTERED = 0;\r\n    uint256 private constant _ENTERED = 1;\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ///////////////////////// Modifiers ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    modifier nonReentrant() {\r\n        ReentrancyStorage storage s = reentrancyStorage();\r\n        if (s.status == _ENTERED) revert ReentrancyError();\r\n        s.status = _ENTERED;\r\n        _;\r\n        s.status = _NOT_ENTERED;\r\n    }\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////// Private Functions /////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    /// @dev fetch local storage\r\n    function reentrancyStorage()\r\n        private\r\n        pure\r\n        returns (ReentrancyStorage storage data)\r\n    {\r\n        bytes32 position = NAMESPACE;\r\n        // solhint-disable-next-line no-inline-assembly\r\n        assembly {\r\n            data.slot := position\r\n        }\r\n    }\r\n}\r\n"
    },
    "src/bridges/errors/GenericErrors.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\nerror InvalidAmount();\r\nerror TokenAddressIsZero();\r\nerror CannotBridgeToSameNetwork();\r\nerror ZeroPostSwapBalance();\r\nerror InvalidBridgeConfigLength();\r\nerror NoSwapDataProvided();\r\nerror NativeValueWithERC();\r\nerror ContractCallNotAllowed();\r\nerror NullAddrIsNotAValidSpender();\r\nerror NullAddrIsNotAnERC20Token();\r\nerror NoTransferToNullAddress();\r\nerror NativeAssetTransferFailed();\r\nerror InvalidContract();\r\nerror InvalidConfig();\r\nerror ZeroAddressProvided();\r\n"
    },
    "src/bridges/errors/StargateErrors.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\nerror SenderNotStargateRouter();\r\nerror NoMsgValueForCrossChainMessage();\r\nerror StargateRouterAddressZero();\r\nerror InvalidSourcePoolId();\r\nerror InvalidDestinationPoolId();\r\n"
    },
    "src/bridges/libs/LibDiamond.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.8.4 <0.9.0;\r\n\r\nimport {IDiamondCut} from \"../interfaces/IDiamondCut.sol\";\r\n\r\nlibrary LibDiamond {\r\n    bytes32 internal constant DIAMOND_STORAGE_POSITION =\r\n        keccak256(\"diamond.standard.diamond.storage\");\r\n\r\n    struct FacetAddressAndPosition {\r\n        address facetAddress;\r\n        uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\r\n    }\r\n\r\n    struct FacetFunctionSelectors {\r\n        bytes4[] functionSelectors;\r\n        uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\r\n    }\r\n\r\n    struct DiamondStorage {\r\n        // maps function selector to the facet address and\r\n        // the position of the selector in the facetFunctionSelectors.selectors array\r\n        mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\r\n        // maps facet addresses to function selectors\r\n        mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\r\n        // facet addresses\r\n        address[] facetAddresses;\r\n        // Used to query if a contract implements an interface.\r\n        // Used to implement ERC-165.\r\n        mapping(bytes4 => bool) supportedInterfaces;\r\n        // owner of the contract\r\n        address contractOwner;\r\n    }\r\n\r\n    function diamondStorage()\r\n        internal\r\n        pure\r\n        returns (DiamondStorage storage ds)\r\n    {\r\n        bytes32 position = DIAMOND_STORAGE_POSITION;\r\n        // solhint-disable-next-line no-inline-assembly\r\n        assembly {\r\n            ds.slot := position\r\n        }\r\n    }\r\n\r\n    event OwnershipTransferred(\r\n        address indexed previousOwner,\r\n        address indexed newOwner\r\n    );\r\n\r\n    function setContractOwner(address _newOwner) internal {\r\n        DiamondStorage storage ds = diamondStorage();\r\n        address previousOwner = ds.contractOwner;\r\n        ds.contractOwner = _newOwner;\r\n        emit OwnershipTransferred(previousOwner, _newOwner);\r\n    }\r\n\r\n    function contractOwner() internal view returns (address contractOwner_) {\r\n        contractOwner_ = diamondStorage().contractOwner;\r\n    }\r\n\r\n    function enforceIsContractOwner() internal view {\r\n        require(\r\n            msg.sender == diamondStorage().contractOwner,\r\n            \"LibDiamond: Must be contract owner\"\r\n        );\r\n    }\r\n\r\n    event DiamondCut(\r\n        IDiamondCut.FacetCut[] _diamondCut,\r\n        address _init,\r\n        bytes _calldata\r\n    );\r\n\r\n    // Internal function version of diamondCut\r\n    function diamondCut(\r\n        IDiamondCut.FacetCut[] memory _diamondCut,\r\n        address _init,\r\n        bytes memory _calldata\r\n    ) internal {\r\n        for (\r\n            uint256 facetIndex;\r\n            facetIndex < _diamondCut.length;\r\n            facetIndex++\r\n        ) {\r\n            IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\r\n            if (action == IDiamondCut.FacetCutAction.Add) {\r\n                addFunctions(\r\n                    _diamondCut[facetIndex].facetAddress,\r\n                    _diamondCut[facetIndex].functionSelectors\r\n                );\r\n            } else if (action == IDiamondCut.FacetCutAction.Replace) {\r\n                replaceFunctions(\r\n                    _diamondCut[facetIndex].facetAddress,\r\n                    _diamondCut[facetIndex].functionSelectors\r\n                );\r\n            } else if (action == IDiamondCut.FacetCutAction.Remove) {\r\n                removeFunctions(\r\n                    _diamondCut[facetIndex].facetAddress,\r\n                    _diamondCut[facetIndex].functionSelectors\r\n                );\r\n            } else {\r\n                revert(\"LibDiamondCut: Incorrect FacetCutAction\");\r\n            }\r\n        }\r\n        emit DiamondCut(_diamondCut, _init, _calldata);\r\n        initializeDiamondCut(_init, _calldata);\r\n    }\r\n\r\n    function addFunctions(\r\n        address _facetAddress,\r\n        bytes4[] memory _functionSelectors\r\n    ) internal {\r\n        require(\r\n            _functionSelectors.length > 0,\r\n            \"LibDiamondCut: No selectors in facet to cut\"\r\n        );\r\n        DiamondStorage storage ds = diamondStorage();\r\n        require(\r\n            _facetAddress != address(0),\r\n            \"LibDiamondCut: Add facet can't be address(0)\"\r\n        );\r\n        uint96 selectorPosition = uint96(\r\n            ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\r\n        );\r\n        // add new facet address if it does not exist\r\n        if (selectorPosition == 0) {\r\n            addFacet(ds, _facetAddress);\r\n        }\r\n        for (\r\n            uint256 selectorIndex;\r\n            selectorIndex < _functionSelectors.length;\r\n            selectorIndex++\r\n        ) {\r\n            bytes4 selector = _functionSelectors[selectorIndex];\r\n            address oldFacetAddress = ds\r\n                .selectorToFacetAndPosition[selector]\r\n                .facetAddress;\r\n            require(\r\n                oldFacetAddress == address(0),\r\n                \"LibDiamondCut: Can't add function that already exists\"\r\n            );\r\n            addFunction(ds, selector, selectorPosition, _facetAddress);\r\n            selectorPosition++;\r\n        }\r\n    }\r\n\r\n    function replaceFunctions(\r\n        address _facetAddress,\r\n        bytes4[] memory _functionSelectors\r\n    ) internal {\r\n        require(\r\n            _functionSelectors.length > 0,\r\n            \"LibDiamondCut: No selectors in facet to cut\"\r\n        );\r\n        DiamondStorage storage ds = diamondStorage();\r\n        require(\r\n            _facetAddress != address(0),\r\n            \"LibDiamondCut: Add facet can't be address(0)\"\r\n        );\r\n        uint96 selectorPosition = uint96(\r\n            ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\r\n        );\r\n        // add new facet address if it does not exist\r\n        if (selectorPosition == 0) {\r\n            addFacet(ds, _facetAddress);\r\n        }\r\n        for (\r\n            uint256 selectorIndex;\r\n            selectorIndex < _functionSelectors.length;\r\n            selectorIndex++\r\n        ) {\r\n            bytes4 selector = _functionSelectors[selectorIndex];\r\n            address oldFacetAddress = ds\r\n                .selectorToFacetAndPosition[selector]\r\n                .facetAddress;\r\n            require(\r\n                oldFacetAddress != _facetAddress,\r\n                \"LibDiamondCut: Can't replace function with same function\"\r\n            );\r\n            removeFunction(ds, oldFacetAddress, selector);\r\n            addFunction(ds, selector, selectorPosition, _facetAddress);\r\n            selectorPosition++;\r\n        }\r\n    }\r\n\r\n    function removeFunctions(\r\n        address _facetAddress,\r\n        bytes4[] memory _functionSelectors\r\n    ) internal {\r\n        require(\r\n            _functionSelectors.length > 0,\r\n            \"LibDiamondCut: No selectors in facet to cut\"\r\n        );\r\n        DiamondStorage storage ds = diamondStorage();\r\n        // if function does not exist then do nothing and return\r\n        require(\r\n            _facetAddress == address(0),\r\n            \"LibDiamondCut: Remove facet address must be address(0)\"\r\n        );\r\n        for (\r\n            uint256 selectorIndex;\r\n            selectorIndex < _functionSelectors.length;\r\n            selectorIndex++\r\n        ) {\r\n            bytes4 selector = _functionSelectors[selectorIndex];\r\n            address oldFacetAddress = ds\r\n                .selectorToFacetAndPosition[selector]\r\n                .facetAddress;\r\n            removeFunction(ds, oldFacetAddress, selector);\r\n        }\r\n    }\r\n\r\n    function addFacet(DiamondStorage storage ds, address _facetAddress)\r\n        internal\r\n    {\r\n        enforceHasContractCode(\r\n            _facetAddress,\r\n            \"LibDiamondCut: New facet has no code\"\r\n        );\r\n        ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\r\n            .facetAddresses\r\n            .length;\r\n        ds.facetAddresses.push(_facetAddress);\r\n    }\r\n\r\n    function addFunction(\r\n        DiamondStorage storage ds,\r\n        bytes4 _selector,\r\n        uint96 _selectorPosition,\r\n        address _facetAddress\r\n    ) internal {\r\n        ds\r\n            .selectorToFacetAndPosition[_selector]\r\n            .functionSelectorPosition = _selectorPosition;\r\n        ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\r\n            _selector\r\n        );\r\n        ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\r\n    }\r\n\r\n    function removeFunction(\r\n        DiamondStorage storage ds,\r\n        address _facetAddress,\r\n        bytes4 _selector\r\n    ) internal {\r\n        require(\r\n            _facetAddress != address(0),\r\n            \"LibDiamondCut: Can't remove function that doesn't exist\"\r\n        );\r\n        // an immutable function is a function defined directly in a diamond\r\n        require(\r\n            _facetAddress != address(this),\r\n            \"LibDiamondCut: Can't remove immutable function\"\r\n        );\r\n        // replace selector with last selector, then delete last selector\r\n        uint256 selectorPosition = ds\r\n            .selectorToFacetAndPosition[_selector]\r\n            .functionSelectorPosition;\r\n        uint256 lastSelectorPosition = ds\r\n            .facetFunctionSelectors[_facetAddress]\r\n            .functionSelectors\r\n            .length - 1;\r\n        // if not the same then replace _selector with lastSelector\r\n        if (selectorPosition != lastSelectorPosition) {\r\n            bytes4 lastSelector = ds\r\n                .facetFunctionSelectors[_facetAddress]\r\n                .functionSelectors[lastSelectorPosition];\r\n            ds.facetFunctionSelectors[_facetAddress].functionSelectors[\r\n                    selectorPosition\r\n                ] = lastSelector;\r\n            ds\r\n                .selectorToFacetAndPosition[lastSelector]\r\n                .functionSelectorPosition = uint96(selectorPosition);\r\n        }\r\n        // delete the last selector\r\n        ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\r\n        delete ds.selectorToFacetAndPosition[_selector];\r\n\r\n        // if no more selectors for facet address then delete the facet address\r\n        if (lastSelectorPosition == 0) {\r\n            // replace facet address with last facet address and delete last facet address\r\n            uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\r\n            uint256 facetAddressPosition = ds\r\n                .facetFunctionSelectors[_facetAddress]\r\n                .facetAddressPosition;\r\n            if (facetAddressPosition != lastFacetAddressPosition) {\r\n                address lastFacetAddress = ds.facetAddresses[\r\n                    lastFacetAddressPosition\r\n                ];\r\n                ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\r\n                ds\r\n                    .facetFunctionSelectors[lastFacetAddress]\r\n                    .facetAddressPosition = facetAddressPosition;\r\n            }\r\n            ds.facetAddresses.pop();\r\n            delete ds\r\n                .facetFunctionSelectors[_facetAddress]\r\n                .facetAddressPosition;\r\n        }\r\n    }\r\n\r\n    function initializeDiamondCut(address _init, bytes memory _calldata)\r\n        internal\r\n    {\r\n        if (_init == address(0)) {\r\n            require(\r\n                _calldata.length == 0,\r\n                \"LibDiamondCut: _init is address(0) but_calldata is not empty\"\r\n            );\r\n        } else {\r\n            require(\r\n                _calldata.length > 0,\r\n                \"LibDiamondCut: _calldata is empty but _init is not address(0)\"\r\n            );\r\n            if (_init != address(this)) {\r\n                enforceHasContractCode(\r\n                    _init,\r\n                    \"LibDiamondCut: _init address has no code\"\r\n                );\r\n            }\r\n            // solhint-disable-next-line avoid-low-level-calls\r\n            (bool success, bytes memory error) = _init.delegatecall(_calldata);\r\n            if (!success) {\r\n                if (error.length > 0) {\r\n                    // bubble up the error\r\n                    revert(string(error));\r\n                } else {\r\n                    revert(\"LibDiamondCut: _init function reverted\");\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    function enforceHasContractCode(\r\n        address _contract,\r\n        string memory _errorMessage\r\n    ) internal view {\r\n        uint256 contractSize;\r\n        // solhint-disable-next-line no-inline-assembly\r\n        assembly {\r\n            contractSize := extcodesize(_contract)\r\n        }\r\n        require(contractSize > 0, _errorMessage);\r\n    }\r\n}\r\n"
    },
    "@openzeppelin/contracts/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.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     *\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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, \"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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) 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        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(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        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(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        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason 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            // 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\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}\n"
    },
    "src/bridges/interfaces/IDiamondCut.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.8.4 <0.9.0;\r\n\r\ninterface IDiamondCut {\r\n    enum FacetCutAction {\r\n        Add,\r\n        Replace,\r\n        Remove\r\n    }\r\n    // Add=0, Replace=1, Remove=2\r\n\r\n    struct FacetCut {\r\n        address facetAddress;\r\n        FacetCutAction action;\r\n        bytes4[] functionSelectors;\r\n    }\r\n\r\n    /// @notice Add/replace/remove any number of functions and optionally execute\r\n    ///         a function with delegatecall\r\n    /// @param _diamondCut Contains the facet addresses and function selectors\r\n    /// @param _init The address of the contract or facet to execute _calldata\r\n    /// @param _calldata A function call, including function selector and arguments\r\n    ///                  _calldata is executed with delegatecall on _init\r\n    function diamondCut(\r\n        FacetCut[] calldata _diamondCut,\r\n        address _init,\r\n        bytes calldata _calldata\r\n    ) external;\r\n\r\n    event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\r\n}\r\n"
    },
    "src/bridges/libs/LibAsset.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\nimport {NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeValueWithERC, NativeAssetTransferFailed} from \"../errors/GenericErrors.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\n\r\n/// @title LibAsset\r\n/// @author Connext <support@connext.network>\r\n/// @notice This library contains helpers for dealing with onchain transfers\r\n///         of assets, including accounting for the native asset `assetId`\r\n///         conventions and any noncompliant ERC20 transfers\r\nlibrary LibAsset {\r\n    uint256 private constant MAX_INT = type(uint256).max;\r\n\r\n    address internal constant NULL_ADDRESS =\r\n        0x0000000000000000000000000000000000000000; //address(0)\r\n\r\n    /// @dev All native assets use the empty address for their asset id\r\n    ///      by convention\r\n\r\n    address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\r\n\r\n    /// @notice Gets the balance of the inheriting contract for the given asset\r\n    /// @param assetId The asset identifier to get the balance of\r\n    /// @return Balance held by contracts using this library\r\n    function getOwnBalance(address assetId) internal view returns (uint256) {\r\n        return\r\n            assetId == NATIVE_ASSETID\r\n                ? address(this).balance\r\n                : IERC20(assetId).balanceOf(address(this));\r\n    }\r\n\r\n    /// @notice Transfers ether from the inheriting contract to a given\r\n    ///         recipient\r\n    /// @param recipient Address to send ether to\r\n    /// @param amount Amount to send to given recipient\r\n    function transferNativeAsset(address payable recipient, uint256 amount)\r\n        private\r\n    {\r\n        if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\r\n        // solhint-disable-next-line avoid-low-level-calls\r\n        (bool success, ) = recipient.call{value: amount}(\"\");\r\n        if (!success) revert NativeAssetTransferFailed();\r\n    }\r\n\r\n    /// @notice Gives MAX approval for another address to spend tokens\r\n    /// @param assetId Token address to transfer\r\n    /// @param spender Address to give spend approval to\r\n    /// @param amount Amount to approve for spending\r\n    function maxApproveERC20(\r\n        IERC20 assetId,\r\n        address spender,\r\n        uint256 amount\r\n    ) internal {\r\n        if (address(assetId) == NATIVE_ASSETID) return;\r\n        if (spender == NULL_ADDRESS) revert NullAddrIsNotAValidSpender();\r\n        uint256 allowance = assetId.allowance(address(this), spender);\r\n        if (allowance < amount)\r\n            SafeERC20.safeApprove(IERC20(assetId), spender, MAX_INT);\r\n    }\r\n\r\n    /// @notice Transfers tokens from the inheriting contract to a given\r\n    ///         recipient\r\n    /// @param assetId Token address to transfer\r\n    /// @param recipient Address to send token to\r\n    /// @param amount Amount to send to given recipient\r\n    function transferERC20(\r\n        address assetId,\r\n        address recipient,\r\n        uint256 amount\r\n    ) private {\r\n        if (isNativeAsset(assetId)) revert NullAddrIsNotAnERC20Token();\r\n        SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\r\n    }\r\n\r\n    /// @notice Transfers tokens from a sender to a given recipient\r\n    /// @param assetId Token address to transfer\r\n    /// @param from Address of sender/owner\r\n    /// @param to Address of recipient/spender\r\n    /// @param amount Amount to transfer from owner to spender\r\n    function transferFromERC20(\r\n        address assetId,\r\n        address from,\r\n        address to,\r\n        uint256 amount\r\n    ) internal {\r\n        if (assetId == NATIVE_ASSETID) revert NullAddrIsNotAnERC20Token();\r\n        if (to == NULL_ADDRESS) revert NoTransferToNullAddress();\r\n        SafeERC20.safeTransferFrom(IERC20(assetId), from, to, amount);\r\n    }\r\n\r\n    /// @notice Deposits an asset into the contract and performs checks to avoid NativeValueWithERC\r\n    /// @param tokenId Token to deposit\r\n    /// @param amount Amount to deposit\r\n    /// @param isNative Wether the token is native or ERC20\r\n    function depositAsset(\r\n        address tokenId,\r\n        uint256 amount,\r\n        bool isNative\r\n    ) internal {\r\n        if (amount == 0) revert InvalidAmount();\r\n        if (isNative) {\r\n            if (msg.value != amount) revert InvalidAmount();\r\n        } else {\r\n            if (msg.value != 0) revert NativeValueWithERC();\r\n            uint256 _fromTokenBalance = LibAsset.getOwnBalance(tokenId);\r\n            LibAsset.transferFromERC20(\r\n                tokenId,\r\n                msg.sender,\r\n                address(this),\r\n                amount\r\n            );\r\n            if (LibAsset.getOwnBalance(tokenId) - _fromTokenBalance != amount)\r\n                revert InvalidAmount();\r\n        }\r\n    }\r\n\r\n    /// @notice Overload for depositAsset(address tokenId, uint256 amount, bool isNative)\r\n    /// @param tokenId Token to deposit\r\n    /// @param amount Amount to deposit\r\n    function depositAsset(address tokenId, uint256 amount) internal {\r\n        return depositAsset(tokenId, amount, tokenId == NATIVE_ASSETID);\r\n    }\r\n\r\n    /// @notice Determines whether the given assetId is the native asset\r\n    /// @param assetId The asset identifier to evaluate\r\n    /// @return Boolean indicating if the asset is the native asset\r\n    function isNativeAsset(address assetId) internal pure returns (bool) {\r\n        return assetId == NATIVE_ASSETID;\r\n    }\r\n\r\n    /// @notice Wrapper function to transfer a given asset (native or erc20) to\r\n    ///         some recipient. Should handle all non-compliant return value\r\n    ///         tokens as well by using the SafeERC20 contract by open zeppelin.\r\n    /// @param assetId Asset id for transfer (address(0) for native asset,\r\n    ///                token address for erc20s)\r\n    /// @param recipient Address to send asset to\r\n    /// @param amount Amount to send to given recipient\r\n    function transferAsset(\r\n        address assetId,\r\n        address payable recipient,\r\n        uint256 amount\r\n    ) internal {\r\n        (assetId == NATIVE_ASSETID)\r\n            ? transferNativeAsset(recipient, amount)\r\n            : transferERC20(assetId, recipient, amount);\r\n    }\r\n\r\n    /// @dev Checks whether the given address is a contract and contains code\r\n    function isContract(address _contractAddr) internal view returns (bool) {\r\n        uint256 size;\r\n        // solhint-disable-next-line no-inline-assembly\r\n        assembly {\r\n            size := extcodesize(_contractAddr)\r\n        }\r\n        return size > 0;\r\n    }\r\n}\r\n"
    },
    "src/common/helpers/BalancesHelperV2.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\n/// @title BalancesHelperV2\r\n/// @author Luke Wickens <luke@pillarproject.io>\r\n/// @notice Used to get account balances of ERC20 tokens and Wrapped Super Tokens\r\n\r\nimport {ISuperfluidToken} from \"@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol\";\r\nimport {IERC20} from \"@openzeppelin/contracts/interfaces/IERC20.sol\";\r\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\r\n\r\ncontract BalancesHelperV2 {\r\n    using Address for address;\r\n\r\n    /// @notice Custom errors to handle address(0)\r\n    error AccountZeroAddress(address account, address token);\r\n    error TokenZeroAddress(address account, address token);\r\n\r\n    constructor() {}\r\n\r\n    /// @notice Returns balances of accounts for multiple ERC20 tokens.\r\n    /// @dev Error thrown if: account or token address is address(0),\r\n    /// large arrays of accounts/tokens are passed in could cause gas block limit issue\r\n    /// @param accounts = Array of accounts addresses\r\n    /// @param tokens = Array of tokens addresses\r\n    /// @return One-dimensional that's accounts.length * tokens.length long. The\r\n    /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\r\n\r\n    function getBalances(address[] calldata accounts, address[] calldata tokens)\r\n        external\r\n        view\r\n        returns (uint256[] memory)\r\n    {\r\n        uint256[] memory result = new uint256[](\r\n            accounts.length * tokens.length\r\n        );\r\n\r\n        for (uint256 i; i < accounts.length; i++) {\r\n            for (uint256 j; j < tokens.length; j++) {\r\n                uint256 index = j + (tokens.length * i);\r\n                result[index] = _getBalance(accounts[i], tokens[j]);\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /// @notice Returns balances of accounts for multiple Wrapped Super Tokens.\r\n    /// @dev Error thrown if: account or token address is address(0),\r\n    /// large arrays of accounts/tokens are passed in could cause gas block limit issue\r\n    /// @param accounts =  Array of accounts addresses\r\n    /// @param tokens = Array of tokens addresses\r\n    /// @return One-dimensional that's accounts.length * tokens.length long. The\r\n    /// array is ordered by all of accounts[0] token balances, then accounts[1] etc.\r\n\r\n    function getSuperfluidWrappedTokenBalances(\r\n        address[] calldata accounts,\r\n        address[] calldata tokens\r\n    ) external view returns (int256[] memory) {\r\n        int256[] memory result = new int256[](accounts.length * tokens.length);\r\n\r\n        for (uint256 i; i < accounts.length; i++) {\r\n            for (uint256 j; j < tokens.length; j++) {\r\n                uint256 index = j + (tokens.length * i);\r\n                result[index] = _getSuperfluidWrappedTokenBalance(\r\n                    accounts[i],\r\n                    tokens[j]\r\n                );\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    /// Private fuctions\r\n\r\n    /// @notice Returns balance of account for an ERC20 token.\r\n    /// @dev Error thrown if: account or token address is address(0)\r\n    /// @param account = account address\r\n    /// @param token = tokens address\r\n    /// @return balance of account as uint256.\r\n\r\n    function _getBalance(address account, address token)\r\n        private\r\n        view\r\n        returns (uint256)\r\n    {\r\n        if (account == address(0)) revert AccountZeroAddress(account, token);\r\n        if (token == address(0)) revert TokenZeroAddress(account, token);\r\n\r\n        bytes memory returnedData = token.functionStaticCall(\r\n            abi.encodeWithSelector(IERC20(token).balanceOf.selector, account)\r\n        );\r\n\r\n        return abi.decode(returnedData, (uint256));\r\n    }\r\n\r\n    /// @notice Returns real balance of a user, taking into consideration all agreements of account\r\n    /// @dev Error thrown if: account or token address is address(0)\r\n    /// @param account = account address\r\n    /// @param token = tokens address\r\n    /// @return available balance of account as int256.\r\n\r\n    function _getSuperfluidWrappedTokenBalance(address account, address token)\r\n        private\r\n        view\r\n        returns (int256)\r\n    {\r\n        if (account == address(0)) revert AccountZeroAddress(account, token);\r\n        if (token == address(0)) revert TokenZeroAddress(account, token);\r\n\r\n        bytes memory returnedData = token.functionStaticCall(\r\n            abi.encodeWithSelector(\r\n                ISuperfluidToken(token).realtimeBalanceOfNow.selector,\r\n                account\r\n            )\r\n        );\r\n\r\n        (int256 availableBalance, , , ) = abi.decode(\r\n            returnedData,\r\n            (int256, uint256, uint256, uint256)\r\n        );\r\n        return availableBalance;\r\n    }\r\n}\r\n"
    },
    "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidToken.sol": {
      "content": "// SPDX-License-Identifier: AGPLv3\npragma solidity >= 0.8.0;\n\nimport { ISuperAgreement } from \"./ISuperAgreement.sol\";\n\n\n/**\n * @title Superfluid token interface\n * @author Superfluid\n */\ninterface ISuperfluidToken {\n\n    /**************************************************************************\n     * Basic information\n     *************************************************************************/\n\n    /**\n     * @dev Get superfluid host contract address\n     */\n    function getHost() external view returns(address host);\n\n    /**\n     * @dev Encoded liquidation type data mainly used for handling stack to deep errors\n     *\n     * Note:\n     * - version: 1\n     * - liquidationType key:\n     *    - 0 = reward account receives reward (PIC period)\n     *    - 1 = liquidator account receives reward (Pleb period)\n     *    - 2 = liquidator account receives reward (Pirate period/bailout)\n     */\n    struct LiquidationTypeData {\n        uint256 version;\n        uint8 liquidationType;\n    }\n\n    /**************************************************************************\n     * Real-time balance functions\n     *************************************************************************/\n\n    /**\n    * @dev Calculate the real balance of a user, taking in consideration all agreements of the account\n    * @param account for the query\n    * @param timestamp Time of balance\n    * @return availableBalance Real-time balance\n    * @return deposit Account deposit\n    * @return owedDeposit Account owed Deposit\n    */\n    function realtimeBalanceOf(\n       address account,\n       uint256 timestamp\n    )\n        external view\n        returns (\n            int256 availableBalance,\n            uint256 deposit,\n            uint256 owedDeposit);\n\n    /**\n     * @notice Calculate the realtime balance given the current host.getNow() value\n     * @dev realtimeBalanceOf with timestamp equals to block timestamp\n     * @param account for the query\n     * @return availableBalance Real-time balance\n     * @return deposit Account deposit\n     * @return owedDeposit Account owed Deposit\n     */\n    function realtimeBalanceOfNow(\n       address account\n    )\n        external view\n        returns (\n            int256 availableBalance,\n            uint256 deposit,\n            uint256 owedDeposit,\n            uint256 timestamp);\n\n    /**\n    * @notice Check if account is critical\n    * @dev A critical account is when availableBalance < 0\n    * @param account The account to check\n    * @param timestamp The time we'd like to check if the account is critical (should use future)\n    * @return isCritical Whether the account is critical\n    */\n    function isAccountCritical(\n        address account,\n        uint256 timestamp\n    )\n        external view\n        returns(bool isCritical);\n\n    /**\n    * @notice Check if account is critical now (current host.getNow())\n    * @dev A critical account is when availableBalance < 0\n    * @param account The account to check\n    * @return isCritical Whether the account is critical\n    */\n    function isAccountCriticalNow(\n        address account\n    )\n        external view\n        returns(bool isCritical);\n\n    /**\n     * @notice Check if account is solvent\n     * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\n     * @param account The account to check\n     * @param timestamp The time we'd like to check if the account is solvent (should use future)\n     * @return isSolvent\n     */\n    function isAccountSolvent(\n        address account,\n        uint256 timestamp\n    )\n        external view\n        returns(bool isSolvent);\n\n    /**\n     * @notice Check if account is solvent now\n     * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance\n     * @param account The account to check\n     * @return isSolvent\n     */\n    function isAccountSolventNow(\n        address account\n    )\n        external view\n        returns(bool isSolvent);\n\n    /**\n    * @notice Get a list of agreements that is active for the account\n    * @dev An active agreement is one that has state for the account\n    * @param account Account to query\n    * @return activeAgreements List of accounts that have non-zero states for the account\n    */\n    function getAccountActiveAgreements(address account)\n       external view\n       returns(ISuperAgreement[] memory activeAgreements);\n\n\n   /**************************************************************************\n    * Super Agreement hosting functions\n    *************************************************************************/\n\n    /**\n     * @dev Create a new agreement\n     * @param id Agreement ID\n     * @param data Agreement data\n     */\n    function createAgreement(\n        bytes32 id,\n        bytes32[] calldata data\n    )\n        external;\n    /**\n     * @dev Agreement created event\n     * @param agreementClass Contract address of the agreement\n     * @param id Agreement ID\n     * @param data Agreement data\n     */\n    event AgreementCreated(\n        address indexed agreementClass,\n        bytes32 id,\n        bytes32[] data\n    );\n\n    /**\n     * @dev Get data of the agreement\n     * @param agreementClass Contract address of the agreement\n     * @param id Agreement ID\n     * @return data Data of the agreement\n     */\n    function getAgreementData(\n        address agreementClass,\n        bytes32 id,\n        uint dataLength\n    )\n        external view\n        returns(bytes32[] memory data);\n\n    /**\n     * @dev Create a new agreement\n     * @param id Agreement ID\n     * @param data Agreement data\n     */\n    function updateAgreementData(\n        bytes32 id,\n        bytes32[] calldata data\n    )\n        external;\n    /**\n     * @dev Agreement updated event\n     * @param agreementClass Contract address of the agreement\n     * @param id Agreement ID\n     * @param data Agreement data\n     */\n    event AgreementUpdated(\n        address indexed agreementClass,\n        bytes32 id,\n        bytes32[] data\n    );\n\n    /**\n     * @dev Close the agreement\n     * @param id Agreement ID\n     */\n    function terminateAgreement(\n        bytes32 id,\n        uint dataLength\n    )\n        external;\n    /**\n     * @dev Agreement terminated event\n     * @param agreementClass Contract address of the agreement\n     * @param id Agreement ID\n     */\n    event AgreementTerminated(\n        address indexed agreementClass,\n        bytes32 id\n    );\n\n    /**\n     * @dev Update agreement state slot\n     * @param account Account to be updated\n     *\n     * NOTE\n     * - To clear the storage out, provide zero-ed array of intended length\n     */\n    function updateAgreementStateSlot(\n        address account,\n        uint256 slotId,\n        bytes32[] calldata slotData\n    )\n        external;\n    /**\n     * @dev Agreement account state updated event\n     * @param agreementClass Contract address of the agreement\n     * @param account Account updated\n     * @param slotId slot id of the agreement state\n     */\n    event AgreementStateUpdated(\n        address indexed agreementClass,\n        address indexed account,\n        uint256 slotId\n    );\n\n    /**\n     * @dev Get data of the slot of the state of an agreement\n     * @param agreementClass Contract address of the agreement\n     * @param account Account to query\n     * @param slotId slot id of the state\n     * @param dataLength length of the state data\n     */\n    function getAgreementStateSlot(\n        address agreementClass,\n        address account,\n        uint256 slotId,\n        uint dataLength\n    )\n        external view\n        returns (bytes32[] memory slotData);\n\n    /**\n     * @notice Settle balance from an account by the agreement\n     * @dev The agreement needs to make sure that the balance delta is balanced afterwards\n     * @param account Account to query.\n     * @param delta Amount of balance delta to be settled\n     *\n     * Modifiers:\n     *  - onlyAgreement\n     */\n    function settleBalance(\n        address account,\n        int256 delta\n    )\n        external;\n\n    /**\n     * @dev Make liquidation payouts (v2)\n     * @param id Agreement ID\n     * @param liquidationTypeData Data regarding the version of the liquidation schema and the type\n     * @param liquidatorAccount Address of the executor of the liquidation\n     * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount\n     * @param targetAccount Account of the stream sender\n     * @param rewardAmount The amount the reward recepient account will receive\n     * @param targetAccountBalanceDelta The amount the sender account balance should change by\n     *\n     * - If a bailout is required (bailoutAmount > 0)\n     *   - the actual reward (single deposit) goes to the executor,\n     *   - while the reward account becomes the bailout account\n     *   - total bailout include: bailout amount + reward amount\n     *   - the targetAccount will be bailed out\n     * - If a bailout is not required\n     *   - the targetAccount will pay the rewardAmount\n     *   - the liquidator (reward account in PIC period) will receive the rewardAmount\n     *\n     * Modifiers:\n     *  - onlyAgreement\n     */\n    function makeLiquidationPayoutsV2\n    (\n        bytes32 id,\n        bytes memory liquidationTypeData,\n        address liquidatorAccount,\n        bool useDefaultRewardAccount,\n        address targetAccount,\n        uint256 rewardAmount,\n        int256 targetAccountBalanceDelta\n    ) external;\n    /**\n     * @dev Agreement liquidation event v2 (including agent account)\n     * @param agreementClass Contract address of the agreement\n     * @param id Agreement ID\n     * @param liquidatorAccount Address of the executor of the liquidation\n     * @param targetAccount Account of the stream sender\n     * @param rewardAccount Account that collects the reward or bails out insolvent accounts\n     * @param rewardAmount The amount the reward recipient account balance should change by\n     * @param targetAccountBalanceDelta The amount the sender account balance should change by\n     * @param liquidationTypeData The encoded liquidation type data including the version (how to decode)\n     *\n     * NOTE:\n     * Reward account rule:\n     * - if the agreement is liquidated during the PIC period\n     *   - the rewardAccount will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount\n     *   - the targetAccount will pay for the rewardAmount\n     * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent\n     *   - the liquidatorAccount will get the rewardAmount (remaining deposit)\n     *   - the targetAccount will pay for the rewardAmount\n     * - if the targetAccount is insolvent\n     *   - the liquidatorAccount will get the rewardAmount (single deposit)\n     *   - the rewardAccount will pay for both the rewardAmount and bailoutAmount\n     *   - the targetAccount will receive the bailoutAmount\n     */\n    event AgreementLiquidatedV2(\n        address indexed agreementClass,\n        bytes32 id,\n        address indexed liquidatorAccount,\n        address indexed targetAccount,\n        address rewardAccount,\n        uint256 rewardAmount,\n        int256 targetAccountBalanceDelta,\n        bytes liquidationTypeData\n    );\n\n    /**************************************************************************\n     * Function modifiers for access control and parameter validations\n     *\n     * While they cannot be explicitly stated in function definitions, they are\n     * listed in function definition comments instead for clarity.\n     *\n     * NOTE: solidity-coverage not supporting it\n     *************************************************************************/\n\n     /// @dev The msg.sender must be host contract\n     //modifier onlyHost() virtual;\n\n    /// @dev The msg.sender must be a listed agreement.\n    //modifier onlyAgreement() virtual;\n\n    /**************************************************************************\n     * DEPRECATED\n     *************************************************************************/\n\n    /**\n     * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy)\n     * @param agreementClass Contract address of the agreement\n     * @param id Agreement ID\n     * @param penaltyAccount Account of the agreement to be penalized\n     * @param rewardAccount Account that collect the reward\n     * @param rewardAmount Amount of liquidation reward\n     *\n     * NOTE:\n     *\n     * [DEPRECATED] Use AgreementLiquidatedV2 instead\n     */\n    event AgreementLiquidated(\n        address indexed agreementClass,\n        bytes32 id,\n        address indexed penaltyAccount,\n        address indexed rewardAccount,\n        uint256 rewardAmount\n    );\n\n    /**\n     * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy)\n     * @param bailoutAccount Account that bailout the penalty account\n     * @param bailoutAmount Amount of account bailout\n     *\n     * NOTE:\n     *\n     * [DEPRECATED] Use AgreementLiquidatedV2 instead\n     */\n    event Bailout(\n        address indexed bailoutAccount,\n        uint256 bailoutAmount\n    );\n\n    /**\n     * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2)\n     * @param liquidatorAccount Account of the agent that performed the liquidation.\n     * @param agreementClass Contract address of the agreement\n     * @param id Agreement ID\n     * @param penaltyAccount Account of the agreement to be penalized\n     * @param bondAccount Account that collect the reward or bailout accounts\n     * @param rewardAmount Amount of liquidation reward\n     * @param bailoutAmount Amount of liquidation bailouot\n     *\n     * NOTE:\n     * Reward account rule:\n     * - if bailout is equal to 0, then\n     *   - the bondAccount will get the rewardAmount,\n     *   - the penaltyAccount will pay for the rewardAmount.\n     * - if bailout is larger than 0, then\n     *   - the liquidatorAccount will get the rewardAmouont,\n     *   - the bondAccount will pay for both the rewardAmount and bailoutAmount,\n     *   - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount.\n     */\n    event AgreementLiquidatedBy(\n        address liquidatorAccount,\n        address indexed agreementClass,\n        bytes32 id,\n        address indexed penaltyAccount,\n        address indexed bondAccount,\n        uint256 rewardAmount,\n        uint256 bailoutAmount\n    );\n}\n"
    },
    "@openzeppelin/contracts/interfaces/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\n"
    },
    "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperAgreement.sol": {
      "content": "// SPDX-License-Identifier: AGPLv3\npragma solidity >= 0.8.0;\n\nimport { ISuperfluidToken } from \"./ISuperfluidToken.sol\";\n\n/**\n * @title Super agreement interface\n * @author Superfluid\n */\ninterface ISuperAgreement {\n\n    /**\n     * @dev Get the type of the agreement class\n     */\n    function agreementType() external view returns (bytes32);\n\n    /**\n     * @dev Calculate the real-time balance for the account of this agreement class\n     * @param account Account the state belongs to\n     * @param time Time used for the calculation\n     * @return dynamicBalance Dynamic balance portion of real-time balance of this agreement\n     * @return deposit Account deposit amount of this agreement\n     * @return owedDeposit Account owed deposit amount of this agreement\n     */\n    function realtimeBalanceOf(\n        ISuperfluidToken token,\n        address account,\n        uint256 time\n    )\n        external\n        view\n        returns (\n            int256 dynamicBalance,\n            uint256 deposit,\n            uint256 owedDeposit\n        );\n\n}\n"
    },
    "src/bridges/facets/CBridgeFacet.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\n/// @title CBridgeFacet\r\n/// @author Luke Wickens <luke@pillarproject.io>\r\n/// @notice cBridge intergration for bridging tokens\r\n\r\nimport {ICBridge} from \"../interfaces/ICBridge.sol\";\r\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\r\nimport {ReentrancyGuard} from \"../../common/helpers/DiamondReentrancyGuard.sol\";\r\nimport {CannotBridgeToSameNetwork, InvalidAmount, InvalidConfig, TokenAddressIsZero, ZeroAddressProvided} from \"../errors/GenericErrors.sol\";\r\nimport {CBSlippageTooLow} from \"../errors/CBridgeErrors.sol\";\r\nimport {LibDiamond} from \"../libs/LibDiamond.sol\";\r\n\r\ncontract CBridgeFacet is ReentrancyGuard {\r\n    using SafeERC20 for IERC20;\r\n    //////////////////////////////////////////////////////////////\r\n    /////////////////////////// Events ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n    event CBInitialized(address cBridge, uint256 chainId);\r\n    event CBTransferStarted(\r\n        string bridgeUsed,\r\n        address token,\r\n        address from,\r\n        address to,\r\n        uint256 qty,\r\n        uint256 chainIdTo\r\n    );\r\n    event CBUpdatedBridge(address newAddress);\r\n    event CBUpdatedSlippageTolerance(uint256 newSlippage);\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////////// Storage ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    bytes32 internal constant NAMESPACE =\r\n        keccak256(\"io.etherspot.facets.cbridge\");\r\n    struct Storage {\r\n        address cbBridge;\r\n        uint256 cbChainId;\r\n        uint32 cbSlippage;\r\n    }\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////////// Structs ///////////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    struct CBridgeData {\r\n        uint64 dstChainId;\r\n        uint64 nonce;\r\n        uint256 qty;\r\n        address to;\r\n        address token;\r\n    }\r\n\r\n    /// @notice initializes state variables for the cBridge facet\r\n    /// @param _cbBridge address of the CBridge router contract\r\n    function cbInitialize(address _cbBridge) external {\r\n        LibDiamond.enforceIsContractOwner();\r\n        if (_cbBridge == address(0)) revert ZeroAddressProvided();\r\n        Storage storage s = getStorage();\r\n        s.cbBridge = _cbBridge;\r\n        s.cbChainId = block.chainid;\r\n        s.cbSlippage = 10000; // equates to 1% - has to be > 0.5% (slippage * 1M)\r\n        emit CBInitialized(_cbBridge, block.chainid);\r\n    }\r\n\r\n    /// @notice initiates token bridging\r\n    /// @param _cbData: provides necessary data for cBridge transfer\r\n\r\n    function cbBridgeTokens(CBridgeData calldata _cbData)\r\n        external\r\n        payable\r\n        nonReentrant\r\n    {\r\n        if (block.chainid == _cbData.dstChainId)\r\n            revert CannotBridgeToSameNetwork();\r\n        if (_cbData.to == address(0)) revert ZeroAddressProvided();\r\n        if (_cbData.qty <= 0) revert InvalidAmount();\r\n        if (_cbData.token == address(0)) revert TokenAddressIsZero();\r\n\r\n        Storage storage s = getStorage();\r\n        address bridge = s.cbBridge;\r\n\r\n        // this contract calls stargate swap()\r\n        IERC20(_cbData.token).safeTransferFrom(\r\n            msg.sender,\r\n            address(this),\r\n            _cbData.qty\r\n        );\r\n        IERC20(_cbData.token).safeApprove(address(bridge), _cbData.qty);\r\n\r\n        ICBridge(bridge).send(\r\n            _cbData.to,\r\n            _cbData.token,\r\n            _cbData.qty,\r\n            _cbData.dstChainId,\r\n            _cbData.nonce,\r\n            s.cbSlippage\r\n        );\r\n\r\n        emit CBTransferStarted(\r\n            \"cbridge\",\r\n            _cbData.token,\r\n            msg.sender,\r\n            _cbData.to,\r\n            _cbData.qty,\r\n            _cbData.dstChainId\r\n        );\r\n    }\r\n\r\n    function cbUpdateSlippageTolerance(uint32 _newSlippage) external {\r\n        // should be > 0.5% (5000)\r\n        if (_newSlippage <= 5000) revert CBSlippageTooLow();\r\n        LibDiamond.enforceIsContractOwner();\r\n        Storage storage s = getStorage();\r\n        s.cbSlippage = _newSlippage;\r\n        emit CBUpdatedSlippageTolerance(_newSlippage);\r\n    }\r\n\r\n    function cbUpdateBridge(address _newAddress) external {\r\n        LibDiamond.enforceIsContractOwner();\r\n        if (_newAddress == address(0)) revert ZeroAddressProvided();\r\n        Storage storage s = getStorage();\r\n        s.cbBridge = _newAddress;\r\n        emit CBUpdatedBridge(_newAddress);\r\n    }\r\n\r\n    //////////////////////////////////////////////////////////////\r\n    ////////////////////// Private Functions /////////////////////\r\n    //////////////////////////////////////////////////////////////\r\n\r\n    /// @dev fetch local storage\r\n    function getStorage() private pure returns (Storage storage s) {\r\n        bytes32 namespace = NAMESPACE;\r\n        // solhint-disable-next-line no-inline-assembly\r\n        assembly {\r\n            s.slot := namespace\r\n        }\r\n    }\r\n}\r\n"
    },
    "src/bridges/interfaces/ICBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\ninterface ICBridge {\r\n    function send(\r\n        address _receiver,\r\n        address _token,\r\n        uint256 _amount,\r\n        uint64 _dstChinId,\r\n        uint64 _nonce,\r\n        uint32 _maxSlippage\r\n    ) external;\r\n\r\n    function sendNative(\r\n        address _receiver,\r\n        uint256 _amount,\r\n        uint64 _dstChinId,\r\n        uint64 _nonce,\r\n        uint32 _maxSlippage\r\n    ) external payable;\r\n\r\n    function relay(\r\n        bytes calldata _relayRequest,\r\n        bytes[] calldata _sigs,\r\n        address[] calldata _signers,\r\n        uint256[] calldata _powers\r\n    ) external;\r\n}\r\n"
    },
    "src/bridges/errors/CBridgeErrors.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\n// solhint-disable-next-line\r\npragma solidity 0.8.4;\r\n\r\nerror CBSlippageTooLow();\r\n"
    },
    "src/bridges/facets/HopFacet.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.4;\r\n\r\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport { IHopBridge } from \"../interfaces/IHopBridge.sol\";\r\nimport { LibAsset } from \"../libs/LibAsset.sol\";\r\nimport { LibDiamond } from \"../libs/LibDiamond.sol\";\r\nimport { ReentrancyGuard } from \"../../common/helpers/DiamondReentrancyGuard.sol\";\r\nimport {\r\n  InvalidAmount,\r\n  InvalidBridgeConfigLength,\r\n  CannotBridgeToSameNetwork,\r\n  NativeValueWithERC,\r\n  InvalidConfig\r\n} from \"../errors/GenericErrors.sol\";\r\n\r\n/**\r\n * @title Hop Protocol Integration\r\n *\r\n * @notice Contract which provides bridging functionality through Hop Protocol\r\n *\r\n */\r\ncontract HopFacet is ReentrancyGuard {\r\n  // storage\r\n\r\n  bytes32 internal constant NAMESPACE = keccak256(\"io.etherspot.facets.hop\");\r\n  struct Storage {\r\n    uint256 chainLayerId;\r\n  }\r\n\r\n  // types\r\n\r\n  struct HopData {\r\n    address bridge;\r\n    address ammWrapper;\r\n    address asset;\r\n    address recipient;\r\n    uint256 chainId;\r\n    uint256 amount;\r\n    uint256 bonderFee;\r\n    uint256 amountOutMin;\r\n    uint256 deadline;\r\n    uint256 destinationAmountOutMin;\r\n    uint256 destinationDeadline;\r\n  }\r\n\r\n  // events\r\n\r\n  /**\r\n   * @dev Emitted when facet initializes\r\n   * @param chainId current chain id\r\n   * @param chainLayerId current chain layer id\r\n   */\r\n  event HopInitialized(\r\n    uint256 chainId,\r\n    uint256 chainLayerId\r\n  );\r\n\r\n  /**\r\n   * @dev Emitted on token swap\r\n   * @param _destination destination chain id\r\n   * @param _bridge address of the bridge on chain _destination,\r\n   * @param _ammWrapper address of the amm wrapper,\r\n   * @param _recipient recipient\r\n   * @param _asset address of the asset\r\n   * @param _amount amount of assets\r\n   * @param _bonderFee fee\r\n   * @param _amountOutMin The minimum amount received after attempting to\r\n   * swap in the destination\r\n   * @param _deadline The deadline for swapping in the destination AMM market.\r\n   * 0 if no * swap is intended.\r\n   * @param _destinationAmountOutMin The minimum amount of tokens to receive after bridging\r\n   * @param _destinationDeadline The time the transaction must be completed\r\n   */\r\n  event HopTokenSwap(\r\n    uint256 indexed _destination,\r\n    address _bridge,\r\n    address _ammWrapper,\r\n    address indexed _recipient,\r\n    address indexed _asset,\r\n    uint256 _amount,\r\n    uint256 _bonderFee,\r\n    uint256 _amountOutMin,\r\n    uint256 _deadline,\r\n    uint256 _destinationAmountOutMin,\r\n    uint256 _destinationDeadline\r\n  );\r\n\r\n\r\n\r\n  // external functions\r\n\r\n  /**\r\n   * @notice Initializes local variables for the Connext facet\r\n   */\r\n  function initHop(uint256 _chainLayerId) external {\r\n    LibDiamond.enforceIsContractOwner();\r\n\r\n    Storage storage s = getStorage();\r\n    s.chainLayerId = _chainLayerId;\r\n\r\n    emit HopInitialized(\r\n      getChainID(),\r\n      _chainLayerId\r\n    );\r\n  }\r\n\r\n  /**\r\n   * @notice Bridges tokens via Hop Protocol\r\n   * @param _hopData data specific to Hop Protocol\r\n   */\r\n  function hopTokenTransfer(\r\n    HopData calldata _hopData\r\n  ) external payable nonReentrant {\r\n    LibAsset.depositAsset(_hopData.asset, _hopData.amount);\r\n\r\n    address bridge;\r\n    if (getLayerId() == 1) {\r\n      bridge = _hopData.bridge;\r\n    } else {\r\n      bridge = _hopData.ammWrapper;\r\n    }\r\n\r\n    if (getChainID() == _hopData.chainId)\r\n      revert CannotBridgeToSameNetwork();\r\n\r\n    // Give Hop approval to bridge tokens\r\n    LibAsset.maxApproveERC20(\r\n      IERC20(_hopData.asset),\r\n      bridge,\r\n      _hopData.amount\r\n    );\r\n\r\n    uint256 value = LibAsset.isNativeAsset(_hopData.asset)\r\n      ? _hopData.amount\r\n      : 0;\r\n\r\n    if (getLayerId() == 1) {\r\n      // Ethereum L1\r\n      IHopBridge(bridge).sendToL2{value: value}(\r\n        _hopData.chainId,\r\n        _hopData.recipient,\r\n        _hopData.amount,\r\n        _hopData.destinationAmountOutMin,\r\n        _hopData.destinationDeadline,\r\n        address(0),\r\n        0\r\n      );\r\n    } else {\r\n      // L2\r\n      IHopBridge(bridge).swapAndSend{value: value}(\r\n        _hopData.chainId,\r\n        _hopData.recipient,\r\n        _hopData.amount,\r\n        _hopData.bonderFee,\r\n        _hopData.amountOutMin,\r\n        _hopData.deadline,\r\n        _hopData.destinationAmountOutMin,\r\n        _hopData.destinationDeadline\r\n      );\r\n    }\r\n    emit HopTokenSwap(\r\n      _hopData.chainId,\r\n      _hopData.bridge,\r\n      _hopData.ammWrapper,\r\n      _hopData.recipient,\r\n      _hopData.asset,\r\n      _hopData.amount,\r\n      _hopData.bonderFee,\r\n      _hopData.amountOutMin,\r\n      _hopData.deadline,\r\n      _hopData.destinationAmountOutMin,\r\n      _hopData.destinationDeadline\r\n    );\r\n  }\r\n\r\n  /// private Methods ///\r\n\r\n  /**\r\n   * @dev returns local storage\r\n   */\r\n  function getStorage() private pure returns (Storage storage s) {\r\n    bytes32 namespace = NAMESPACE;\r\n    // solhint-disable-next-line no-inline-assembly\r\n    assembly {\r\n      s.slot := namespace\r\n    }\r\n  }\r\n\r\n  /**\r\n   * @dev returns current chain layer number\r\n   * @return uint256 layer number\r\n   */\r\n  function getLayerId() private view returns (uint256) {\r\n    return getStorage().chainLayerId;\r\n  }\r\n\r\n  /**\r\n   * @dev fetch chain id\r\n   */\r\n  function getChainID() private view returns (uint256) {\r\n    uint256 id;\r\n    // solhint-disable-next-line no-inline-assembly\r\n    assembly {\r\n        id := chainid()\r\n    }\r\n    return id;\r\n  }\r\n}\r\n"
    },
    "src/bridges/interfaces/IHopBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.4;\r\n\r\ninterface IHopBridge {\r\n  function sendToL2(\r\n    uint256 chainId,\r\n    address recipient,\r\n    uint256 amount,\r\n    uint256 amountOutMin,\r\n    uint256 deadline,\r\n    address relayer,\r\n    uint256 relayerFee\r\n  ) external payable;\r\n\r\n  function swapAndSend(\r\n    uint256 chainId,\r\n    address recipient,\r\n    uint256 amount,\r\n    uint256 bonderFee,\r\n    uint256 amountOutMin,\r\n    uint256 deadline,\r\n    uint256 destinationAmountOutMin,\r\n    uint256 destinationDeadline\r\n  ) external payable;\r\n}\r\n"
    }
  },
  "settings": {
    "evmVersion": "istanbul",
    "metadata": {
      "bytecodeHash": "none",
      "useLiteralContent": true
    },
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    }
  }
}