creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/IAuthentication.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\ninterface IAuthentication {\n    /**\n     * @dev Returns the action identifier associated with the external function described by `selector`.\n     */\n    function getActionId(bytes4 selector) external view returns (bytes32);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ISignaturesValidator.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev Interface for the SignatureValidator helper, used to support meta-transactions.\n */\ninterface ISignaturesValidator {\n    /**\n     * @dev Returns the EIP712 domain separator.\n     */\n    function getDomainSeparator() external view returns (bytes32);\n\n    /**\n     * @dev Returns the next nonce used by an address to sign messages.\n     */\n    function getNextNonce(address user) external view returns (uint256);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ITemporarilyPausable.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev Interface for the TemporarilyPausable helper.\n */\ninterface ITemporarilyPausable {\n    /**\n     * @dev Emitted every time the pause state changes by `_setPaused`.\n     */\n    event PausedStateChanged(bool paused);\n\n    /**\n     * @dev Returns the current paused state.\n     */\n    function getPausedState()\n        external\n        view\n        returns (\n            bool paused,\n            uint256 pauseWindowEndTime,\n            uint256 bufferPeriodEndTime\n        );\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IWETH.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"../openzeppelin/IERC20.sol\";\n\n/**\n * @dev Interface for WETH9.\n * See https://github.com/gnosis/canonical-weth/blob/0dd1ea3e295eef916d0c6223ec63141137d22d67/contracts/WETH9.sol\n */\ninterface IWETH is IERC20 {\n    function deposit() external payable;\n\n    function withdraw(uint256 amount) external;\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\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 `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, 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 `sender` to `recipient` 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 sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\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"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev This is an empty interface used to represent either ERC20-conforming token contracts or ETH (using the zero\n * address sentinel value). We're just relying on the fact that `interface` can be used to declare new address-like\n * types.\n *\n * This concept is unrelated to a Pool's Asset Managers.\n */\ninterface IAsset {\n    // solhint-disable-previous-line no-empty-blocks\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IAuthorizer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\ninterface IAuthorizer {\n    /**\n     * @dev Returns true if `account` can perform the action described by `actionId` in the contract `where`.\n     */\n    function canPerform(\n        bytes32 actionId,\n        address account,\n        address where\n    ) external view returns (bool);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\n// Inspired by Aave Protocol's IFlashLoanReceiver.\n\nimport \"../solidity-utils/openzeppelin/IERC20.sol\";\n\ninterface IFlashLoanRecipient {\n    /**\n     * @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient.\n     *\n     * At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this\n     * call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the\n     * Vault, or else the entire flash loan will revert.\n     *\n     * `userData` is the same value passed in the `IVault.flashLoan` call.\n     */\n    function receiveFlashLoan(\n        IERC20[] memory tokens,\n        uint256[] memory amounts,\n        uint256[] memory feeAmounts,\n        bytes memory userData\n    ) external;\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IProtocolFeesCollector.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\npragma experimental ABIEncoderV2;\n\nimport \"../solidity-utils/openzeppelin/IERC20.sol\";\n\nimport \"./IVault.sol\";\nimport \"./IAuthorizer.sol\";\n\ninterface IProtocolFeesCollector {\n    event SwapFeePercentageChanged(uint256 newSwapFeePercentage);\n    event FlashLoanFeePercentageChanged(uint256 newFlashLoanFeePercentage);\n\n    function withdrawCollectedFees(\n        IERC20[] calldata tokens,\n        uint256[] calldata amounts,\n        address recipient\n    ) external;\n\n    function setSwapFeePercentage(uint256 newSwapFeePercentage) external;\n\n    function setFlashLoanFeePercentage(uint256 newFlashLoanFeePercentage) external;\n\n    function getSwapFeePercentage() external view returns (uint256);\n\n    function getFlashLoanFeePercentage() external view returns (uint256);\n\n    function getCollectedFeeAmounts(IERC20[] memory tokens) external view returns (uint256[] memory feeAmounts);\n\n    function getAuthorizer() external view returns (IAuthorizer);\n\n    function vault() external view returns (IVault);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma experimental ABIEncoderV2;\n\nimport \"../solidity-utils/openzeppelin/IERC20.sol\";\nimport \"../solidity-utils/helpers/IAuthentication.sol\";\nimport \"../solidity-utils/helpers/ISignaturesValidator.sol\";\nimport \"../solidity-utils/helpers/ITemporarilyPausable.sol\";\nimport \"../solidity-utils/misc/IWETH.sol\";\n\nimport \"./IAsset.sol\";\nimport \"./IAuthorizer.sol\";\nimport \"./IFlashLoanRecipient.sol\";\nimport \"./IProtocolFeesCollector.sol\";\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev Full external interface for the Vault core contract - no external or public methods exist in the contract that\n * don't override one of these declarations.\n */\ninterface IVault is ISignaturesValidator, ITemporarilyPausable, IAuthentication {\n    // Generalities about the Vault:\n    //\n    // - Whenever documentation refers to 'tokens', it strictly refers to ERC20-compliant token contracts. Tokens are\n    // transferred out of the Vault by calling the `IERC20.transfer` function, and transferred in by calling\n    // `IERC20.transferFrom`. In these cases, the sender must have previously allowed the Vault to use their tokens by\n    // calling `IERC20.approve`. The only deviation from the ERC20 standard that is supported is functions not returning\n    // a boolean value: in these scenarios, a non-reverting call is assumed to be successful.\n    //\n    // - All non-view functions in the Vault are non-reentrant: calling them while another one is mid-execution (e.g.\n    // while execution control is transferred to a token contract during a swap) will result in a revert. View\n    // functions can be called in a re-reentrant way, but doing so might cause them to return inconsistent results.\n    // Contracts calling view functions in the Vault must make sure the Vault has not already been entered.\n    //\n    // - View functions revert if referring to either unregistered Pools, or unregistered tokens for registered Pools.\n\n    // Authorizer\n    //\n    // Some system actions are permissioned, like setting and collecting protocol fees. This permissioning system exists\n    // outside of the Vault in the Authorizer contract: the Vault simply calls the Authorizer to check if the caller\n    // can perform a given action.\n\n    /**\n     * @dev Returns the Vault's Authorizer.\n     */\n    function getAuthorizer() external view returns (IAuthorizer);\n\n    /**\n     * @dev Sets a new Authorizer for the Vault. The caller must be allowed by the current Authorizer to do this.\n     *\n     * Emits an `AuthorizerChanged` event.\n     */\n    function setAuthorizer(IAuthorizer newAuthorizer) external;\n\n    /**\n     * @dev Emitted when a new authorizer is set by `setAuthorizer`.\n     */\n    event AuthorizerChanged(IAuthorizer indexed newAuthorizer);\n\n    // Relayers\n    //\n    // Additionally, it is possible for an account to perform certain actions on behalf of another one, using their\n    // Vault ERC20 allowance and Internal Balance. These accounts are said to be 'relayers' for these Vault functions,\n    // and are expected to be smart contracts with sound authentication mechanisms. For an account to be able to wield\n    // this power, two things must occur:\n    //  - The Authorizer must grant the account the permission to be a relayer for the relevant Vault function. This\n    //    means that Balancer governance must approve each individual contract to act as a relayer for the intended\n    //    functions.\n    //  - Each user must approve the relayer to act on their behalf.\n    // This double protection means users cannot be tricked into approving malicious relayers (because they will not\n    // have been allowed by the Authorizer via governance), nor can malicious relayers approved by a compromised\n    // Authorizer or governance drain user funds, since they would also need to be approved by each individual user.\n\n    /**\n     * @dev Returns true if `user` has approved `relayer` to act as a relayer for them.\n     */\n    function hasApprovedRelayer(address user, address relayer) external view returns (bool);\n\n    /**\n     * @dev Allows `relayer` to act as a relayer for `sender` if `approved` is true, and disallows it otherwise.\n     *\n     * Emits a `RelayerApprovalChanged` event.\n     */\n    function setRelayerApproval(\n        address sender,\n        address relayer,\n        bool approved\n    ) external;\n\n    /**\n     * @dev Emitted every time a relayer is approved or disapproved by `setRelayerApproval`.\n     */\n    event RelayerApprovalChanged(address indexed relayer, address indexed sender, bool approved);\n\n    // Internal Balance\n    //\n    // Users can deposit tokens into the Vault, where they are allocated to their Internal Balance, and later\n    // transferred or withdrawn. It can also be used as a source of tokens when joining Pools, as a destination\n    // when exiting them, and as either when performing swaps. This usage of Internal Balance results in greatly reduced\n    // gas costs when compared to relying on plain ERC20 transfers, leading to large savings for frequent users.\n    //\n    // Internal Balance management features batching, which means a single contract call can be used to perform multiple\n    // operations of different kinds, with different senders and recipients, at once.\n\n    /**\n     * @dev Returns `user`'s Internal Balance for a set of tokens.\n     */\n    function getInternalBalance(address user, IERC20[] memory tokens) external view returns (uint256[] memory);\n\n    /**\n     * @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer)\n     * and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as\n     * it lets integrators reuse a user's Vault allowance.\n     *\n     * For each operation, if the caller is not `sender`, it must be an authorized relayer for them.\n     */\n    function manageUserBalance(UserBalanceOp[] memory ops) external payable;\n\n    /**\n     * @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received\n     without manual WETH wrapping or unwrapping.\n     */\n    struct UserBalanceOp {\n        UserBalanceOpKind kind;\n        IAsset asset;\n        uint256 amount;\n        address sender;\n        address payable recipient;\n    }\n\n    // There are four possible operations in `manageUserBalance`:\n    //\n    // - DEPOSIT_INTERNAL\n    // Increases the Internal Balance of the `recipient` account by transferring tokens from the corresponding\n    // `sender`. The sender must have allowed the Vault to use their tokens via `IERC20.approve()`.\n    //\n    // ETH can be used by passing the ETH sentinel value as the asset and forwarding ETH in the call: it will be wrapped\n    // and deposited as WETH. Any ETH amount remaining will be sent back to the caller (not the sender, which is\n    // relevant for relayers).\n    //\n    // Emits an `InternalBalanceChanged` event.\n    //\n    //\n    // - WITHDRAW_INTERNAL\n    // Decreases the Internal Balance of the `sender` account by transferring tokens to the `recipient`.\n    //\n    // ETH can be used by passing the ETH sentinel value as the asset. This will deduct WETH instead, unwrap it and send\n    // it to the recipient as ETH.\n    //\n    // Emits an `InternalBalanceChanged` event.\n    //\n    //\n    // - TRANSFER_INTERNAL\n    // Transfers tokens from the Internal Balance of the `sender` account to the Internal Balance of `recipient`.\n    //\n    // Reverts if the ETH sentinel value is passed.\n    //\n    // Emits an `InternalBalanceChanged` event.\n    //\n    //\n    // - TRANSFER_EXTERNAL\n    // Transfers tokens from `sender` to `recipient`, using the Vault's ERC20 allowance. This is typically used by\n    // relayers, as it lets them reuse a user's Vault allowance.\n    //\n    // Reverts if the ETH sentinel value is passed.\n    //\n    // Emits an `ExternalBalanceTransfer` event.\n\n    enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL }\n\n    /**\n     * @dev Emitted when a user's Internal Balance changes, either from calls to `manageUserBalance`, or through\n     * interacting with Pools using Internal Balance.\n     *\n     * Because Internal Balance works exclusively with ERC20 tokens, ETH deposits and withdrawals will use the WETH\n     * address.\n     */\n    event InternalBalanceChanged(address indexed user, IERC20 indexed token, int256 delta);\n\n    /**\n     * @dev Emitted when a user's Vault ERC20 allowance is used by the Vault to transfer tokens to an external account.\n     */\n    event ExternalBalanceTransfer(IERC20 indexed token, address indexed sender, address recipient, uint256 amount);\n\n    // Pools\n    //\n    // There are three specialization settings for Pools, which allow for cheaper swaps at the cost of reduced\n    // functionality:\n    //\n    //  - General: no specialization, suited for all Pools. IGeneralPool is used for swap request callbacks, passing the\n    // balance of all tokens in the Pool. These Pools have the largest swap costs (because of the extra storage reads),\n    // which increase with the number of registered tokens.\n    //\n    //  - Minimal Swap Info: IMinimalSwapInfoPool is used instead of IGeneralPool, which saves gas by only passing the\n    // balance of the two tokens involved in the swap. This is suitable for some pricing algorithms, like the weighted\n    // constant product one popularized by Balancer V1. Swap costs are smaller compared to general Pools, and are\n    // independent of the number of registered tokens.\n    //\n    //  - Two Token: only allows two tokens to be registered. This achieves the lowest possible swap gas cost. Like\n    // minimal swap info Pools, these are called via IMinimalSwapInfoPool.\n\n    enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN }\n\n    /**\n     * @dev Registers the caller account as a Pool with a given specialization setting. Returns the Pool's ID, which\n     * is used in all Pool-related functions. Pools cannot be deregistered, nor can the Pool's specialization be\n     * changed.\n     *\n     * The caller is expected to be a smart contract that implements either `IGeneralPool` or `IMinimalSwapInfoPool`,\n     * depending on the chosen specialization setting. This contract is known as the Pool's contract.\n     *\n     * Note that the same contract may register itself as multiple Pools with unique Pool IDs, or in other words,\n     * multiple Pools may share the same contract.\n     *\n     * Emits a `PoolRegistered` event.\n     */\n    function registerPool(PoolSpecialization specialization) external returns (bytes32);\n\n    /**\n     * @dev Emitted when a Pool is registered by calling `registerPool`.\n     */\n    event PoolRegistered(bytes32 indexed poolId, address indexed poolAddress, PoolSpecialization specialization);\n\n    /**\n     * @dev Returns a Pool's contract address and specialization setting.\n     */\n    function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);\n\n    /**\n     * @dev Registers `tokens` for the `poolId` Pool. Must be called by the Pool's contract.\n     *\n     * Pools can only interact with tokens they have registered. Users join a Pool by transferring registered tokens,\n     * exit by receiving registered tokens, and can only swap registered tokens.\n     *\n     * Each token can only be registered once. For Pools with the Two Token specialization, `tokens` must have a length\n     * of two, that is, both tokens must be registered in the same `registerTokens` call, and they must be sorted in\n     * ascending order.\n     *\n     * The `tokens` and `assetManagers` arrays must have the same length, and each entry in these indicates the Asset\n     * Manager for the corresponding token. Asset Managers can manage a Pool's tokens via `managePoolBalance`,\n     * depositing and withdrawing them directly, and can even set their balance to arbitrary amounts. They are therefore\n     * expected to be highly secured smart contracts with sound design principles, and the decision to register an\n     * Asset Manager should not be made lightly.\n     *\n     * Pools can choose not to assign an Asset Manager to a given token by passing in the zero address. Once an Asset\n     * Manager is set, it cannot be changed except by deregistering the associated token and registering again with a\n     * different Asset Manager.\n     *\n     * Emits a `TokensRegistered` event.\n     */\n    function registerTokens(\n        bytes32 poolId,\n        IERC20[] memory tokens,\n        address[] memory assetManagers\n    ) external;\n\n    /**\n     * @dev Emitted when a Pool registers tokens by calling `registerTokens`.\n     */\n    event TokensRegistered(bytes32 indexed poolId, IERC20[] tokens, address[] assetManagers);\n\n    /**\n     * @dev Deregisters `tokens` for the `poolId` Pool. Must be called by the Pool's contract.\n     *\n     * Only registered tokens (via `registerTokens`) can be deregistered. Additionally, they must have zero total\n     * balance. For Pools with the Two Token specialization, `tokens` must have a length of two, that is, both tokens\n     * must be deregistered in the same `deregisterTokens` call.\n     *\n     * A deregistered token can be re-registered later on, possibly with a different Asset Manager.\n     *\n     * Emits a `TokensDeregistered` event.\n     */\n    function deregisterTokens(bytes32 poolId, IERC20[] memory tokens) external;\n\n    /**\n     * @dev Emitted when a Pool deregisters tokens by calling `deregisterTokens`.\n     */\n    event TokensDeregistered(bytes32 indexed poolId, IERC20[] tokens);\n\n    /**\n     * @dev Returns detailed information for a Pool's registered token.\n     *\n     * `cash` is the number of tokens the Vault currently holds for the Pool. `managed` is the number of tokens\n     * withdrawn and held outside the Vault by the Pool's token Asset Manager. The Pool's total balance for `token`\n     * equals the sum of `cash` and `managed`.\n     *\n     * Internally, `cash` and `managed` are stored using 112 bits. No action can ever cause a Pool's token `cash`,\n     * `managed` or `total` balance to be greater than 2^112 - 1.\n     *\n     * `lastChangeBlock` is the number of the block in which `token`'s total balance was last modified (via either a\n     * join, exit, swap, or Asset Manager update). This value is useful to avoid so-called 'sandwich attacks', for\n     * example when developing price oracles. A change of zero (e.g. caused by a swap with amount zero) is considered a\n     * change for this purpose, and will update `lastChangeBlock`.\n     *\n     * `assetManager` is the Pool's token Asset Manager.\n     */\n    function getPoolTokenInfo(bytes32 poolId, IERC20 token)\n        external\n        view\n        returns (\n            uint256 cash,\n            uint256 managed,\n            uint256 lastChangeBlock,\n            address assetManager\n        );\n\n    /**\n     * @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of\n     * the tokens' `balances` changed.\n     *\n     * The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all\n     * Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order.\n     *\n     * If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same\n     * order as passed to `registerTokens`.\n     *\n     * Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are\n     * the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo`\n     * instead.\n     */\n    function getPoolTokens(bytes32 poolId)\n        external\n        view\n        returns (\n            IERC20[] memory tokens,\n            uint256[] memory balances,\n            uint256 lastChangeBlock\n        );\n\n    /**\n     * @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will\n     * trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized\n     * Pool shares.\n     *\n     * If the caller is not `sender`, it must be an authorized relayer for them.\n     *\n     * The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount\n     * to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces\n     * these maximums.\n     *\n     * If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable\n     * this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the\n     * WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent\n     * back to the caller (not the sender, which is important for relayers).\n     *\n     * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when\n     * interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be\n     * sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final\n     * `assets` array might not be sorted. Pools with no registered tokens cannot be joined.\n     *\n     * If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only\n     * be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be\n     * withdrawn from Internal Balance: attempting to do so will trigger a revert.\n     *\n     * This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement\n     * their own custom logic. This typically requires additional information from the user (such as the expected number\n     * of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed\n     * directly to the Pool's contract, as is `recipient`.\n     *\n     * Emits a `PoolBalanceChanged` event.\n     */\n    function joinPool(\n        bytes32 poolId,\n        address sender,\n        address recipient,\n        JoinPoolRequest memory request\n    ) external payable;\n\n    struct JoinPoolRequest {\n        IAsset[] assets;\n        uint256[] maxAmountsIn;\n        bytes userData;\n        bool fromInternalBalance;\n    }\n\n    /**\n     * @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will\n     * trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized\n     * Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see\n     * `getPoolTokenInfo`).\n     *\n     * If the caller is not `sender`, it must be an authorized relayer for them.\n     *\n     * The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum\n     * token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault:\n     * it just enforces these minimums.\n     *\n     * If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To\n     * enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead\n     * of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit.\n     *\n     * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when\n     * interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must\n     * be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the\n     * final `assets` array might not be sorted. Pools with no registered tokens cannot be exited.\n     *\n     * If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise,\n     * an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to\n     * do so will trigger a revert.\n     *\n     * `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the\n     * `tokens` array. This array must match the Pool's registered tokens.\n     *\n     * This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement\n     * their own custom logic. This typically requires additional information from the user (such as the expected number\n     * of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and\n     * passed directly to the Pool's contract.\n     *\n     * Emits a `PoolBalanceChanged` event.\n     */\n    function exitPool(\n        bytes32 poolId,\n        address sender,\n        address payable recipient,\n        ExitPoolRequest memory request\n    ) external;\n\n    struct ExitPoolRequest {\n        IAsset[] assets;\n        uint256[] minAmountsOut;\n        bytes userData;\n        bool toInternalBalance;\n    }\n\n    /**\n     * @dev Emitted when a user joins or exits a Pool by calling `joinPool` or `exitPool`, respectively.\n     */\n    event PoolBalanceChanged(\n        bytes32 indexed poolId,\n        address indexed liquidityProvider,\n        IERC20[] tokens,\n        int256[] deltas,\n        uint256[] protocolFeeAmounts\n    );\n\n    enum PoolBalanceChangeKind { JOIN, EXIT }\n\n    // Swaps\n    //\n    // Users can swap tokens with Pools by calling the `swap` and `batchSwap` functions. To do this,\n    // they need not trust Pool contracts in any way: all security checks are made by the Vault. They must however be\n    // aware of the Pools' pricing algorithms in order to estimate the prices Pools will quote.\n    //\n    // The `swap` function executes a single swap, while `batchSwap` can perform multiple swaps in sequence.\n    // In each individual swap, tokens of one kind are sent from the sender to the Pool (this is the 'token in'),\n    // and tokens of another kind are sent from the Pool to the recipient in exchange (this is the 'token out').\n    // More complex swaps, such as one token in to multiple tokens out can be achieved by batching together\n    // individual swaps.\n    //\n    // There are two swap kinds:\n    //  - 'given in' swaps, where the amount of tokens in (sent to the Pool) is known, and the Pool determines (via the\n    // `onSwap` hook) the amount of tokens out (to send to the recipient).\n    //  - 'given out' swaps, where the amount of tokens out (received from the Pool) is known, and the Pool determines\n    // (via the `onSwap` hook) the amount of tokens in (to receive from the sender).\n    //\n    // Additionally, it is possible to chain swaps using a placeholder input amount, which the Vault replaces with\n    // the calculated output of the previous swap. If the previous swap was 'given in', this will be the calculated\n    // tokenOut amount. If the previous swap was 'given out', it will use the calculated tokenIn amount. These extended\n    // swaps are known as 'multihop' swaps, since they 'hop' through a number of intermediate tokens before arriving at\n    // the final intended token.\n    //\n    // In all cases, tokens are only transferred in and out of the Vault (or withdrawn from and deposited into Internal\n    // Balance) after all individual swaps have been completed, and the net token balance change computed. This makes\n    // certain swap patterns, such as multihops, or swaps that interact with the same token pair in multiple Pools, cost\n    // much less gas than they would otherwise.\n    //\n    // It also means that under certain conditions it is possible to perform arbitrage by swapping with multiple\n    // Pools in a way that results in net token movement out of the Vault (profit), with no tokens being sent in (only\n    // updating the Pool's internal accounting).\n    //\n    // To protect users from front-running or the market changing rapidly, they supply a list of 'limits' for each token\n    // involved in the swap, where either the maximum number of tokens to send (by passing a positive value) or the\n    // minimum amount of tokens to receive (by passing a negative value) is specified.\n    //\n    // Additionally, a 'deadline' timestamp can also be provided, forcing the swap to fail if it occurs after\n    // this point in time (e.g. if the transaction failed to be included in a block promptly).\n    //\n    // If interacting with Pools that hold WETH, it is possible to both send and receive ETH directly: the Vault will do\n    // the wrapping and unwrapping. To enable this mechanism, the IAsset sentinel value (the zero address) must be\n    // passed in the `assets` array instead of the WETH address. Note that it is possible to combine ETH and WETH in the\n    // same swap. Any excess ETH will be sent back to the caller (not the sender, which is relevant for relayers).\n    //\n    // Finally, Internal Balance can be used when either sending or receiving tokens.\n\n    enum SwapKind { GIVEN_IN, GIVEN_OUT }\n\n    /**\n     * @dev Performs a swap with a single Pool.\n     *\n     * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens\n     * taken from the Pool, which must be greater than or equal to `limit`.\n     *\n     * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens\n     * sent to the Pool, which must be less than or equal to `limit`.\n     *\n     * Internal Balance usage and the recipient are determined by the `funds` struct.\n     *\n     * Emits a `Swap` event.\n     */\n    function swap(\n        SingleSwap memory singleSwap,\n        FundManagement memory funds,\n        uint256 limit,\n        uint256 deadline\n    ) external payable returns (uint256);\n\n    /**\n     * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on\n     * the `kind` value.\n     *\n     * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address).\n     * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault.\n     *\n     * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be\n     * used to extend swap behavior.\n     */\n    struct SingleSwap {\n        bytes32 poolId;\n        SwapKind kind;\n        IAsset assetIn;\n        IAsset assetOut;\n        uint256 amount;\n        bytes userData;\n    }\n\n    /**\n     * @dev Performs a series of swaps with one or multiple Pools. In each individual swap, the caller determines either\n     * the amount of tokens sent to or received from the Pool, depending on the `kind` value.\n     *\n     * Returns an array with the net Vault asset balance deltas. Positive amounts represent tokens (or ETH) sent to the\n     * Vault, and negative amounts represent tokens (or ETH) sent by the Vault. Each delta corresponds to the asset at\n     * the same index in the `assets` array.\n     *\n     * Swaps are executed sequentially, in the order specified by the `swaps` array. Each array element describes a\n     * Pool, the token to be sent to this Pool, the token to receive from it, and an amount that is either `amountIn` or\n     * `amountOut` depending on the swap kind.\n     *\n     * Multihop swaps can be executed by passing an `amount` value of zero for a swap. This will cause the amount in/out\n     * of the previous swap to be used as the amount in for the current one. In a 'given in' swap, 'tokenIn' must equal\n     * the previous swap's `tokenOut`. For a 'given out' swap, `tokenOut` must equal the previous swap's `tokenIn`.\n     *\n     * The `assets` array contains the addresses of all assets involved in the swaps. These are either token addresses,\n     * or the IAsset sentinel value for ETH (the zero address). Each entry in the `swaps` array specifies tokens in and\n     * out by referencing an index in `assets`. Note that Pools never interact with ETH directly: it will be wrapped to\n     * or unwrapped from WETH by the Vault.\n     *\n     * Internal Balance usage, sender, and recipient are determined by the `funds` struct. The `limits` array specifies\n     * the minimum or maximum amount of each token the vault is allowed to transfer.\n     *\n     * `batchSwap` can be used to make a single swap, like `swap` does, but doing so requires more gas than the\n     * equivalent `swap` call.\n     *\n     * Emits `Swap` events.\n     */\n    function batchSwap(\n        SwapKind kind,\n        BatchSwapStep[] memory swaps,\n        IAsset[] memory assets,\n        FundManagement memory funds,\n        int256[] memory limits,\n        uint256 deadline\n    ) external payable returns (int256[] memory);\n\n    /**\n     * @dev Data for each individual swap executed by `batchSwap`. The asset in and out fields are indexes into the\n     * `assets` array passed to that function, and ETH assets are converted to WETH.\n     *\n     * If `amount` is zero, the multihop mechanism is used to determine the actual amount based on the amount in/out\n     * from the previous swap, depending on the swap kind.\n     *\n     * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be\n     * used to extend swap behavior.\n     */\n    struct BatchSwapStep {\n        bytes32 poolId;\n        uint256 assetInIndex;\n        uint256 assetOutIndex;\n        uint256 amount;\n        bytes userData;\n    }\n\n    /**\n     * @dev Emitted for each individual swap performed by `swap` or `batchSwap`.\n     */\n    event Swap(\n        bytes32 indexed poolId,\n        IERC20 indexed tokenIn,\n        IERC20 indexed tokenOut,\n        uint256 amountIn,\n        uint256 amountOut\n    );\n\n    /**\n     * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the\n     * `recipient` account.\n     *\n     * If the caller is not `sender`, it must be an authorized relayer for them.\n     *\n     * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20\n     * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender`\n     * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of\n     * `joinPool`.\n     *\n     * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of\n     * transferred. This matches the behavior of `exitPool`.\n     *\n     * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a\n     * revert.\n     */\n    struct FundManagement {\n        address sender;\n        bool fromInternalBalance;\n        address payable recipient;\n        bool toInternalBalance;\n    }\n\n    /**\n     * @dev Simulates a call to `batchSwap`, returning an array of Vault asset deltas. Calls to `swap` cannot be\n     * simulated directly, but an equivalent `batchSwap` call can and will yield the exact same result.\n     *\n     * Each element in the array corresponds to the asset at the same index, and indicates the number of tokens (or ETH)\n     * the Vault would take from the sender (if positive) or send to the recipient (if negative). The arguments it\n     * receives are the same that an equivalent `batchSwap` call would receive.\n     *\n     * Unlike `batchSwap`, this function performs no checks on the sender or recipient field in the `funds` struct.\n     * This makes it suitable to be called by off-chain applications via eth_call without needing to hold tokens,\n     * approve them for the Vault, or even know a user's address.\n     *\n     * Note that this function is not 'view' (due to implementation details): the client code must explicitly execute\n     * eth_call instead of eth_sendTransaction.\n     */\n    function queryBatchSwap(\n        SwapKind kind,\n        BatchSwapStep[] memory swaps,\n        IAsset[] memory assets,\n        FundManagement memory funds\n    ) external returns (int256[] memory assetDeltas);\n\n    // Flash Loans\n\n    /**\n     * @dev Performs a 'flash loan', sending tokens to `recipient`, executing the `receiveFlashLoan` hook on it,\n     * and then reverting unless the tokens plus a proportional protocol fee have been returned.\n     *\n     * The `tokens` and `amounts` arrays must have the same length, and each entry in these indicates the loan amount\n     * for each token contract. `tokens` must be sorted in ascending order.\n     *\n     * The 'userData' field is ignored by the Vault, and forwarded as-is to `recipient` as part of the\n     * `receiveFlashLoan` call.\n     *\n     * Emits `FlashLoan` events.\n     */\n    function flashLoan(\n        IFlashLoanRecipient recipient,\n        IERC20[] memory tokens,\n        uint256[] memory amounts,\n        bytes memory userData\n    ) external;\n\n    /**\n     * @dev Emitted for each individual flash loan performed by `flashLoan`.\n     */\n    event FlashLoan(IFlashLoanRecipient indexed recipient, IERC20 indexed token, uint256 amount, uint256 feeAmount);\n\n    // Asset Management\n    //\n    // Each token registered for a Pool can be assigned an Asset Manager, which is able to freely withdraw the Pool's\n    // tokens from the Vault, deposit them, or assign arbitrary values to its `managed` balance (see\n    // `getPoolTokenInfo`). This makes them extremely powerful and dangerous. Even if an Asset Manager only directly\n    // controls one of the tokens in a Pool, a malicious manager could set that token's balance to manipulate the\n    // prices of the other tokens, and then drain the Pool with swaps. The risk of using Asset Managers is therefore\n    // not constrained to the tokens they are managing, but extends to the entire Pool's holdings.\n    //\n    // However, a properly designed Asset Manager smart contract can be safely used for the Pool's benefit,\n    // for example by lending unused tokens out for interest, or using them to participate in voting protocols.\n    //\n    // This concept is unrelated to the IAsset interface.\n\n    /**\n     * @dev Performs a set of Pool balance operations, which may be either withdrawals, deposits or updates.\n     *\n     * Pool Balance management features batching, which means a single contract call can be used to perform multiple\n     * operations of different kinds, with different Pools and tokens, at once.\n     *\n     * For each operation, the caller must be registered as the Asset Manager for `token` in `poolId`.\n     */\n    function managePoolBalance(PoolBalanceOp[] memory ops) external;\n\n    struct PoolBalanceOp {\n        PoolBalanceOpKind kind;\n        bytes32 poolId;\n        IERC20 token;\n        uint256 amount;\n    }\n\n    /**\n     * Withdrawals decrease the Pool's cash, but increase its managed balance, leaving the total balance unchanged.\n     *\n     * Deposits increase the Pool's cash, but decrease its managed balance, leaving the total balance unchanged.\n     *\n     * Updates don't affect the Pool's cash balance, but because the managed balance changes, it does alter the total.\n     * The external amount can be either increased or decreased by this call (i.e., reporting a gain or a loss).\n     */\n    enum PoolBalanceOpKind { WITHDRAW, DEPOSIT, UPDATE }\n\n    /**\n     * @dev Emitted when a Pool's token Asset Manager alters its balance via `managePoolBalance`.\n     */\n    event PoolBalanceManaged(\n        bytes32 indexed poolId,\n        address indexed assetManager,\n        IERC20 indexed token,\n        int256 cashDelta,\n        int256 managedDelta\n    );\n\n    // Protocol Fees\n    //\n    // Some operations cause the Vault to collect tokens in the form of protocol fees, which can then be withdrawn by\n    // permissioned accounts.\n    //\n    // There are two kinds of protocol fees:\n    //\n    //  - flash loan fees: charged on all flash loans, as a percentage of the amounts lent.\n    //\n    //  - swap fees: a percentage of the fees charged by Pools when performing swaps. For a number of reasons, including\n    // swap gas costs and interface simplicity, protocol swap fees are not charged on each individual swap. Rather,\n    // Pools are expected to keep track of how much they have charged in swap fees, and pay any outstanding debts to the\n    // Vault when they are joined or exited. This prevents users from joining a Pool with unpaid debt, as well as\n    // exiting a Pool in debt without first paying their share.\n\n    /**\n     * @dev Returns the current protocol fee module.\n     */\n    function getProtocolFeesCollector() external view returns (IProtocolFeesCollector);\n\n    /**\n     * @dev Safety mechanism to pause most Vault operations in the event of an emergency - typically detection of an\n     * error in some part of the system.\n     *\n     * The Vault can only be paused during an initial time period, after which pausing is forever disabled.\n     *\n     * While the contract is paused, the following features are disabled:\n     * - depositing and transferring internal balance\n     * - transferring external balance (using the Vault's allowance)\n     * - swaps\n     * - joining Pools\n     * - Asset Manager interactions\n     *\n     * Internal Balance can still be withdrawn, and Pools exited.\n     */\n    function setPaused(bool paused) external;\n\n    /**\n     * @dev Returns the Vault's WETH instance.\n     */\n    function WETH() external view returns (IWETH);\n    // solhint-disable-previous-line func-name-mixedcase\n}\n"
      },
      "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol": {
        "content": "pragma solidity >=0.6.2;\n\ninterface IUniswapV2Router01 {\n    function factory() external pure returns (address);\n    function WETH() external pure returns (address);\n\n    function addLiquidity(\n        address tokenA,\n        address tokenB,\n        uint amountADesired,\n        uint amountBDesired,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountA, uint amountB, uint liquidity);\n    function addLiquidityETH(\n        address token,\n        uint amountTokenDesired,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);\n    function removeLiquidity(\n        address tokenA,\n        address tokenB,\n        uint liquidity,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountA, uint amountB);\n    function removeLiquidityETH(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountToken, uint amountETH);\n    function removeLiquidityWithPermit(\n        address tokenA,\n        address tokenB,\n        uint liquidity,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountA, uint amountB);\n    function removeLiquidityETHWithPermit(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountToken, uint amountETH);\n    function swapExactTokensForTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external returns (uint[] memory amounts);\n    function swapTokensForExactTokens(\n        uint amountOut,\n        uint amountInMax,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external returns (uint[] memory amounts);\n    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\n        external\n        payable\n        returns (uint[] memory amounts);\n    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)\n        external\n        returns (uint[] memory amounts);\n    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\n        external\n        returns (uint[] memory amounts);\n    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)\n        external\n        payable\n        returns (uint[] memory amounts);\n\n    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);\n    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);\n    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);\n    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\n    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);\n}\n"
      },
      "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol": {
        "content": "pragma solidity >=0.6.2;\n\nimport './IUniswapV2Router01.sol';\n\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\n    function removeLiquidityETHSupportingFeeOnTransferTokens(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountETH);\n    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountETH);\n\n    function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external;\n    function swapExactETHForTokensSupportingFeeOnTransferTokens(\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external payable;\n    function swapExactTokensForETHSupportingFeeOnTransferTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external;\n}\n"
      },
      "contracts/Arbitrage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.18;\n\nimport \"@balancer-labs/v2-interfaces/contracts/vault/IVault.sol\";\nimport \"@balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol\";\nimport \"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol\";\n\ncontract Arbitrage is IFlashLoanRecipient {\n    IVault private constant vault =\n        IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);\n\n    IUniswapV2Router02 public immutable sRouter;\n    IUniswapV2Router02 public immutable uRouter;\n    address public owner;\n\n    constructor(address _sRouter, address _uRouter) {\n        sRouter = IUniswapV2Router02(_sRouter); // Sushiswap\n        uRouter = IUniswapV2Router02(_uRouter); // Uniswap\n        owner = msg.sender;\n    }\n\n    function executeTrade(\n        bool _startOnUniswap,\n        address _token0,\n        address _token1,\n        uint256 _flashAmount\n    ) external {\n        bytes memory data = abi.encode(_startOnUniswap, _token0, _token1);\n\n        // Token to flash loan, by default we are flash loaning 1 token.\n        IERC20[] memory tokens = new IERC20[](1);\n        tokens[0] = IERC20(_token0);\n\n        // Flash loan amount.\n        uint256[] memory amounts = new uint256[](1);\n        amounts[0] = _flashAmount;\n\n        vault.flashLoan(this, tokens, amounts, data);\n    }\n\n    function receiveFlashLoan(\n        IERC20[] memory tokens,\n        uint256[] memory amounts,\n        uint256[] memory feeAmounts,\n        bytes memory userData\n    ) external override {\n        require(msg.sender == address(vault));\n\n        uint256 flashAmount = amounts[0];\n\n        (bool startOnUniswap, address token0, address token1) = abi.decode(\n            userData,\n            (bool, address, address)\n        );\n\n        // Use the money here!\n        address[] memory path = new address[](2);\n\n        path[0] = token0;\n        path[1] = token1;\n\n        if (startOnUniswap) {\n            _swapOnUniswap(path, flashAmount, 0);\n\n            path[0] = token1;\n            path[1] = token0;\n\n            _swapOnSushiswap(\n                path,\n                IERC20(token1).balanceOf(address(this)),\n                flashAmount\n            );\n        } else {\n            _swapOnSushiswap(path, flashAmount, 0);\n\n            path[0] = token1;\n            path[1] = token0;\n\n            _swapOnUniswap(\n                path,\n                IERC20(token1).balanceOf(address(this)),\n                flashAmount\n            );\n        }\n\n        IERC20(token0).transfer(address(vault), flashAmount);\n\n        IERC20(token0).transfer(owner, IERC20(token0).balanceOf(address(this)));\n    }\n\n    // -- INTERNAL FUNCTIONS -- //\n\n    function _swapOnUniswap(\n        address[] memory _path,\n        uint256 _amountIn,\n        uint256 _amountOut\n    ) internal {\n        require(\n            IERC20(_path[0]).approve(address(uRouter), _amountIn),\n            \"Uniswap approval failed.\"\n        );\n\n        uRouter.swapExactTokensForTokens(\n            _amountIn,\n            _amountOut,\n            _path,\n            address(this),\n            (block.timestamp + 1200)\n        );\n    }\n\n    function _swapOnSushiswap(\n        address[] memory _path,\n        uint256 _amountIn,\n        uint256 _amountOut\n    ) internal {\n        require(\n            IERC20(_path[0]).approve(address(sRouter), _amountIn),\n            \"Sushiswap approval failed.\"\n        );\n\n        sRouter.swapExactTokensForTokens(\n            _amountIn,\n            _amountOut,\n            _path,\n            address(this),\n            (block.timestamp + 1200)\n        );\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": false,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}