creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/libs/BalancerUtilities.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n// Copyright (c) 2023 Tokemak Foundation. All rights reserved.\n\npragma solidity 0.8.17;\n\nimport { IERC20 } from \"openzeppelin-contracts/token/ERC20/IERC20.sol\";\n\nimport { IVault } from \"src/interfaces/external/balancer/IVault.sol\";\nimport { IBalancerPool } from \"src/interfaces/external/balancer/IBalancerPool.sol\";\nimport { IBalancerMetaStablePool } from \"src/interfaces/external/balancer/IBalancerMetaStablePool.sol\";\nimport { IBalancerComposableStablePool } from \"src/interfaces/external/balancer/IBalancerComposableStablePool.sol\";\n\nlibrary BalancerUtilities {\n    error BalancerVaultReentrancy();\n\n    // 400 is Balancers Vault REENTRANCY error code\n    bytes32 internal constant REENTRANCY_ERROR_HASH = keccak256(abi.encodeWithSignature(\"Error(string)\", \"BAL#400\"));\n\n    /**\n     * @notice Verifies reentrancy to the Balancer Vault\n     * @dev Reverts if gets BAL#400 error\n     */\n    function checkReentrancy(address balancerVault) external view {\n        // solhint-disable max-line-length\n        // https://github.com/balancer/balancer-v2-monorepo/blob/227683919a7031615c0bc7f144666cdf3883d212/pkg/pool-utils/contracts/lib/VaultReentrancyLib.sol\n        (, bytes memory returnData) = balancerVault.staticcall{ gas: 10_000 }(\n            abi.encodeWithSelector(IVault.manageUserBalance.selector, new IVault.UserBalanceOp[](0))\n        );\n        if (keccak256(returnData) == REENTRANCY_ERROR_HASH) {\n            revert BalancerVaultReentrancy();\n        }\n    }\n\n    /**\n     * @notice Checks if a given address is Balancer Composable pool\n     * @dev Using the presence of a getBptIndex() fn as an indicator of pool type\n     */\n    function isComposablePool(address pool) public view returns (bool) {\n        // slither-disable-start low-level-calls\n        // solhint-disable-next-line no-unused-vars\n        (bool success, bytes memory data) = pool.staticcall(abi.encodeWithSignature(\"getBptIndex()\"));\n        if (success) {\n            return data.length > 0;\n        }\n        // slither-disable-end low-level-calls\n        return success;\n    }\n\n    /**\n     * @dev This helper function is a fast and cheap way to convert between IERC20[] and IAsset[] types\n     */\n    function _convertERC20sToAddresses(IERC20[] memory tokens) internal pure returns (address[] memory assets) {\n        //slither-disable-start assembly\n        //solhint-disable-next-line no-inline-assembly\n        assembly {\n            assets := tokens\n        }\n        //slither-disable-end assembly\n    }\n\n    /**\n     * @dev This helper function to retrieve Balancer pool tokens\n     */\n    function _getPoolTokens(\n        IVault balancerVault,\n        address balancerPool\n    ) internal view returns (IERC20[] memory assets, uint256[] memory balances) {\n        bytes32 poolId = IBalancerPool(balancerPool).getPoolId();\n\n        (assets, balances,) = balancerVault.getPoolTokens(poolId);\n    }\n\n    /// @notice This function retrieves tokens (skipping the BPT) from Balancer composable pools\n    function _getComposablePoolTokensSkipBpt(\n        IVault balancerVault,\n        address balancerPool\n    ) internal view returns (IERC20[] memory tokens, uint256[] memory balances) {\n        (IERC20[] memory allTokens, uint256[] memory allBalances) =\n            BalancerUtilities._getPoolTokens(balancerVault, balancerPool);\n\n        uint256 nTokens = allTokens.length;\n        tokens = new IERC20[](nTokens - 1);\n        balances = new uint256[](nTokens - 1);\n\n        uint256 lastIndex = 0;\n        uint256 bptIndex = IBalancerComposableStablePool(balancerPool).getBptIndex();\n        for (uint256 i = 0; i < nTokens;) {\n            // skip pool token\n            if (i == bptIndex) {\n                unchecked {\n                    ++i;\n                }\n                continue;\n            }\n            // copy tokens and balances\n            tokens[lastIndex] = allTokens[i];\n            balances[lastIndex] = allBalances[i];\n            unchecked {\n                ++i;\n                ++lastIndex;\n            }\n        }\n    }\n\n    /**\n     * @notice Gets the virtual price of a Balancer metastable pool with an invariant adjustment\n     * @dev removes accrued admin fees that haven't been taken yet by Balancer\n     */\n    function _getMetaStableVirtualPrice(\n        IVault balancerVault,\n        address balancerPool\n    ) internal view returns (uint256 virtualPrice) {\n        IBalancerMetaStablePool pool = IBalancerMetaStablePool(balancerPool);\n        virtualPrice = pool.getRate(); // e18\n\n        uint256 totalSupply = pool.totalSupply(); // e18\n        uint256 unscaledInv = (virtualPrice * totalSupply) / 1e18; // e18\n        uint256 lastInvariant = pool.getLastInvariant(); // e18\n        if (unscaledInv > lastInvariant) {\n            uint256 delta = unscaledInv - lastInvariant; // e18 - e18 -> e18\n            uint256 swapFee = balancerVault.getProtocolFeesCollector().getSwapFeePercentage(); //e18\n            uint256 protocolPortion = ((delta * swapFee) / 1e18); // e18\n            uint256 scaledInv = unscaledInv - protocolPortion; // e18 - e18 -> e18\n            virtualPrice = scaledInv * 1e18 / totalSupply; // e36 / e18 -> e18\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/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"
      },
      "src/interfaces/external/balancer/IVault.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.17;\n\nimport { IERC20 } from \"openzeppelin-contracts/token/ERC20/IERC20.sol\";\nimport { IProtocolFeesCollector } from \"src/interfaces/external/balancer/IProtocolFeesCollector.sol\";\nimport { IAsset } from \"src/interfaces/external/balancer/IAsset.sol\";\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 {\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 {\n        GENERAL,\n        MINIMAL_SWAP_INFO,\n        TWO_TOKEN\n    }\n\n    enum JoinKind {\n        INIT,\n        EXACT_TOKENS_IN_FOR_BPT_OUT,\n        TOKEN_IN_FOR_EXACT_BPT_OUT,\n        ALL_TOKENS_IN_FOR_EXACT_BPT_OUT\n    }\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        address 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 {\n        DEPOSIT_INTERNAL,\n        WITHDRAW_INTERNAL,\n        TRANSFER_INTERNAL,\n        TRANSFER_EXTERNAL\n    }\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 Returns a Pool's contract address and specialization setting.\n     */\n    function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);\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 (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock);\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(\n        bytes32 poolId,\n        IERC20 token\n    ) external view returns (uint256 cash, uint256 managed, uint256 lastChangeBlock, address assetManager);\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        address[] 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        address[] assets;\n        uint256[] minAmountsOut;\n        bytes userData;\n        bool toInternalBalance;\n    }\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, IERC20 indexed tokenIn, IERC20 indexed tokenOut, uint256 amountIn, uint256 amountOut\n    );\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 {\n        GIVEN_IN,\n        GIVEN_OUT\n    }\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        address assetIn;\n        address assetOut;\n        uint256 amount;\n        bytes userData;\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    function getProtocolFeesCollector() external view returns (IProtocolFeesCollector);\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"
      },
      "src/interfaces/external/balancer/IBalancerPool.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC20Metadata } from \"openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface IBalancerPool is IERC20Metadata {\n    /// @notice returns total supply of Balancer pool\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @notice gets Balancer poolId\n     * @return bytes32 poolId\n     */\n    function getPoolId() external view returns (bytes32);\n}\n"
      },
      "src/interfaces/external/balancer/IBalancerMetaStablePool.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IRateProvider } from \"src/interfaces/external/balancer/IRateProvider.sol\";\n\ninterface IBalancerMetaStablePool {\n    function getPoolId() external view returns (bytes32);\n\n    function getRate() external view returns (uint256);\n\n    function getLastInvariant() external view returns (uint256);\n\n    function getLatest(uint8 x) external view returns (uint256);\n\n    function totalSupply() external view returns (uint256);\n\n    function getSwapFeePercentage() external view returns (uint256);\n\n    function getRateProviders() external view returns (IRateProvider[] memory);\n}\n"
      },
      "src/interfaces/external/balancer/IBalancerComposableStablePool.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC20 } from \"openzeppelin-contracts/token/ERC20/IERC20.sol\";\n\ninterface IBalancerComposableStablePool {\n    function getActualSupply() external view returns (uint256);\n\n    function getBptIndex() external view returns (uint256);\n\n    function getPoolId() external view returns (bytes32);\n\n    function getRate() external view returns (uint256);\n\n    function getTokenRate(IERC20 token) external view returns (uint256);\n}\n"
      },
      "src/interfaces/external/balancer/IProtocolFeesCollector.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IProtocolFeesCollector {\n    function getSwapFeePercentage() external view returns (uint256);\n}\n"
      },
      "src/interfaces/external/balancer/IAsset.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.17;\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"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "src/interfaces/external/balancer/IRateProvider.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/>.\npragma solidity 0.8.17;\n\ninterface IRateProvider {\n    function getRate() external view returns (uint256);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "forge-std/=lib/forge-std/src/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "src/=src/",
        "test/=test/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
        "erc4626-tests/=lib/erc4626-tests/",
        "prb-math/=lib/prb-math/",
        "crytic/properties/=lib/properties/",
        "ERC4626/=lib/properties/lib/ERC4626/contracts/",
        "properties/=lib/properties/contracts/",
        "solmate/=lib/properties/lib/solmate/src/",
        "usingtellor/=lib/usingtellor/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs"
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "viaIR": false,
      "libraries": {
        "src/destinations/adapters/BalancerBeethovenAdapter.sol": {
          "BalancerBeethovenAdapter": "0x122cDdB001dF0006D046b2Bf7eC59ad01630fB75"
        },
        "src/destinations/adapters/rewards/AuraRewardsAdapter.sol": {
          "AuraRewards": "0xF5f6dd22538e472ACbE2a1877cE199D0801494c5"
        },
        "src/destinations/adapters/staking/AuraAdapter.sol": {
          "AuraStaking": "0x508633033ba8b810Bbf23677D74FB575bFdc0208"
        },
        "src/destinations/adapters/staking/ConvexAdapter.sol": {
          "ConvexStaking": "0x52Cd2861f3AC5b19F6f8610b47248d9a74FAD63B"
        },
        "src/libs/BalancerUtilities.sol": {
          "BalancerUtilities": "0x04Ae00491cbE37FA3f68b7708E006644464a2915"
        }
      }
    }
  }}