{
  "address": "0xf824c0C3F15f2440f4932C02BBD01e7344B56910",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_amplificationParameter",
          "type": "uint256"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [],
      "name": "amplificationParameter",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getAmplificationParameter",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "internalType": "uint256[]",
          "name": "balances",
          "type": "uint256[]"
        },
        {
          "internalType": "uint256",
          "name": "indexIn",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "indexOut",
          "type": "uint256"
        }
      ],
      "name": "onSwapGivenIn",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "internalType": "uint256[]",
          "name": "balances",
          "type": "uint256[]"
        },
        {
          "internalType": "uint256",
          "name": "indexIn",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "indexOut",
          "type": "uint256"
        }
      ],
      "name": "onSwapGivenOut",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_amplificationParameter",
          "type": "uint256"
        }
      ],
      "name": "updateAmplificationParameter",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0x9b615dc8bd0958a50be588496c6db714e41ca04f47c91ffc4f27d4dbf44a4a36",
  "receipt": {
    "to": null,
    "from": "0xd4b33434Cb36df9286Ef5132FCFb8062c96aC56E",
    "contractAddress": "0xf824c0C3F15f2440f4932C02BBD01e7344B56910",
    "transactionIndex": 6,
    "gasUsed": "599229",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0xaaf96943258322cf31f998511f31523b02456708afea84e7f03d381428cccb07",
    "transactionHash": "0x9b615dc8bd0958a50be588496c6db714e41ca04f47c91ffc4f27d4dbf44a4a36",
    "logs": [],
    "blockNumber": 4692965,
    "cumulativeGasUsed": "1742860",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "2500000000000000000000"
  ],
  "solcInputHash": "4270066cb79148326df731b732884fa6",
  "metadata": "{\"compiler\":{\"version\":\"0.7.1+commit.f4a555be\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amplificationParameter\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"amplificationParameter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAmplificationParameter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"balances\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"indexIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"indexOut\",\"type\":\"uint256\"}],\"name\":\"onSwapGivenIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"balances\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"indexIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"indexOut\",\"type\":\"uint256\"}],\"name\":\"onSwapGivenOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amplificationParameter\",\"type\":\"uint256\"}],\"name\":\"updateAmplificationParameter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src.sol/amm/StableSwap.sol\":\"StableSwap\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src.sol/amm/StableSwap.sol\":{\"content\":\"// Wrapper StableMath\\npragma solidity ^0.7.0;\\n\\nimport \\\"./lib/math/FixedPoint.sol\\\";\\n\\nimport \\\"./pools/stable/StablePoolUserDataHelpers.sol\\\";\\nimport \\\"./pools/stable/StableMath.sol\\\";\\n\\ncontract StableSwap is StableMath {\\n    using FixedPoint for uint256;\\n    using StablePoolUserDataHelpers for bytes;\\n    address immutable owner;\\n    uint256 public amplificationParameter;\\n\\n    constructor(uint256 _amplificationParameter) {\\n        owner = msg.sender;\\n        _require(_amplificationParameter >= _MIN_AMP, Errors.MIN_AMP);\\n        _require(_amplificationParameter <= _MAX_AMP, Errors.MAX_AMP);\\n\\n        amplificationParameter = _amplificationParameter;\\n    }\\n\\n    modifier onlyOwner {\\n        require(msg.sender == owner, \\\"Only owner can call this function.\\\");\\n        _;\\n    }\\n\\n    function updateAmplificationParameter(uint256 _amplificationParameter)\\n        public\\n        onlyOwner\\n    {\\n        amplificationParameter = _amplificationParameter;\\n    }\\n\\n    function getAmplificationParameter() external view returns (uint256) {\\n        return amplificationParameter;\\n    }\\n\\n    // Swap\\n\\n    function onSwapGivenIn(\\n        uint256 amount,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut\\n    ) external view virtual returns (uint256) {\\n        uint256 amountOut =\\n            StableMath._calcOutGivenIn(\\n                amplificationParameter,\\n                balances,\\n                indexIn,\\n                indexOut,\\n                amount\\n            );\\n\\n        return amountOut;\\n    }\\n\\n    function onSwapGivenOut(\\n        uint256 amount,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut\\n    ) external view virtual returns (uint256) {\\n        uint256 amountIn =\\n            StableMath._calcInGivenOut(\\n                amplificationParameter,\\n                balances,\\n                indexIn,\\n                indexOut,\\n                amount\\n            );\\n\\n        return amountIn;\\n    }\\n}\\n\",\"keccak256\":\"0xe6c8af61c54b6cba85bb13b4b8a2ea8095994dfe5dd7a393a41950abdc404bce\"},\"src.sol/amm/lib/helpers/Authentication.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;\\n\\nimport \\\"./BalancerErrors.sol\\\";\\nimport \\\"./IAuthentication.sol\\\";\\n\\n/**\\n * @dev Building block for performing access control on external functions.\\n *\\n * This contract is used via the `authenticate` modifier (or the `_authenticateCaller` function), which can be applied\\n * to external functions to only make them callable by authorized accounts.\\n *\\n * Derived contracts must implement the `_canPerform` function, which holds the actual access control logic.\\n */\\nabstract contract Authentication is IAuthentication {\\n    bytes32 private immutable _actionIdDisambiguator;\\n\\n    /**\\n     * @dev The main purpose of the `actionIdDisambiguator` is to prevent accidental function selector collisions in\\n     * multi contract systems.\\n     *\\n     * There are two main uses for it:\\n     *  - if the contract is a singleton, any unique identifier can be used to make the associated action identifiers\\n     *    unique. The contract's own address is a good option.\\n     *  - if the contract belongs to a family that shares action identifiers for the same functions, an identifier\\n     *    shared by the entire family (and no other contract) should be used instead.\\n     */\\n    constructor(bytes32 actionIdDisambiguator) {\\n        _actionIdDisambiguator = actionIdDisambiguator;\\n    }\\n\\n    /**\\n     * @dev Reverts unless the caller is allowed to call this function. Should only be applied to external functions.\\n     */\\n    modifier authenticate() {\\n        _authenticateCaller();\\n        _;\\n    }\\n\\n    /**\\n     * @dev Reverts unless the caller is allowed to call the entry point function.\\n     */\\n    function _authenticateCaller() internal view {\\n        bytes32 actionId = getActionId(msg.sig);\\n        _require(_canPerform(actionId, msg.sender), Errors.SENDER_NOT_ALLOWED);\\n    }\\n\\n    function getActionId(bytes4 selector) public view override returns (bytes32) {\\n        // Each external function is dynamically assigned an action identifier as the hash of the disambiguator and the\\n        // function selector. Disambiguation is necessary to avoid potential collisions in the function selectors of\\n        // multiple contracts.\\n        return keccak256(abi.encodePacked(_actionIdDisambiguator, selector));\\n    }\\n\\n    function _canPerform(bytes32 actionId, address user) internal view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0xea892213ec2967f53e26a0dd833bde01e4d9b6e49dd91e6c59ff00044f83c28d\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/lib/helpers/BalancerErrors.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;\\n\\n// solhint-disable\\n\\n/**\\n * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are\\n * supported.\\n */\\nfunction _require(bool condition, uint256 errorCode) pure {\\n    if (!condition) _revert(errorCode);\\n}\\n\\n/**\\n * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported.\\n */\\nfunction _revert(uint256 errorCode) pure {\\n    // We're going to dynamically create a revert string based on the error code, with the following format:\\n    // 'BAL#{errorCode}'\\n    // where the code is left-padded with zeroes to three digits (so they range from 000 to 999).\\n    //\\n    // We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a\\n    // number (8 to 16 bits) than the individual string characters.\\n    //\\n    // The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a\\n    // much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a\\n    // safe place to rely on it without worrying about how its usage might affect e.g. memory contents.\\n    assembly {\\n        // First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999\\n        // range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for\\n        // the '0' character.\\n\\n        let units := add(mod(errorCode, 10), 0x30)\\n\\n        errorCode := div(errorCode, 10)\\n        let tenths := add(mod(errorCode, 10), 0x30)\\n\\n        errorCode := div(errorCode, 10)\\n        let hundreds := add(mod(errorCode, 10), 0x30)\\n\\n        // With the individual characters, we can now construct the full string. The \\\"BAL#\\\" part is a known constant\\n        // (0x42414c23): we simply shift this by 24 (to provide space for the 3 bytes of the error code), and add the\\n        // characters to it, each shifted by a multiple of 8.\\n        // The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits\\n        // per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte\\n        // array).\\n\\n        let revertReason := shl(200, add(0x42414c23000000, add(add(units, shl(8, tenths)), shl(16, hundreds))))\\n\\n        // We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded\\n        // message will have the following layout:\\n        // [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ]\\n\\n        // The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We\\n        // also write zeroes to the next 28 bytes of memory, but those are about to be overwritten.\\n        mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n        // Next is the offset to the location of the string, which will be placed immediately after (20 bytes away).\\n        mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n        // The string length is fixed: 7 characters.\\n        mstore(0x24, 7)\\n        // Finally, the string itself is stored.\\n        mstore(0x44, revertReason)\\n\\n        // Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of\\n        // the encoded message is therefore 4 + 32 + 32 + 32 = 100.\\n        revert(0, 100)\\n    }\\n}\\n\\nlibrary Errors {\\n    // Math\\n    uint256 internal constant ADD_OVERFLOW = 0;\\n    uint256 internal constant SUB_OVERFLOW = 1;\\n    uint256 internal constant SUB_UNDERFLOW = 2;\\n    uint256 internal constant MUL_OVERFLOW = 3;\\n    uint256 internal constant ZERO_DIVISION = 4;\\n    uint256 internal constant DIV_INTERNAL = 5;\\n    uint256 internal constant X_OUT_OF_BOUNDS = 6;\\n    uint256 internal constant Y_OUT_OF_BOUNDS = 7;\\n    uint256 internal constant PRODUCT_OUT_OF_BOUNDS = 8;\\n    uint256 internal constant INVALID_EXPONENT = 9;\\n\\n    // Input\\n    uint256 internal constant OUT_OF_BOUNDS = 100;\\n    uint256 internal constant UNSORTED_ARRAY = 101;\\n    uint256 internal constant UNSORTED_TOKENS = 102;\\n    uint256 internal constant INPUT_LENGTH_MISMATCH = 103;\\n    uint256 internal constant ZERO_TOKEN = 104;\\n\\n    // Shared pools\\n    uint256 internal constant MIN_TOKENS = 200;\\n    uint256 internal constant MAX_TOKENS = 201;\\n    uint256 internal constant MAX_SWAP_FEE_PERCENTAGE = 202;\\n    uint256 internal constant MIN_SWAP_FEE_PERCENTAGE = 203;\\n    uint256 internal constant MINIMUM_BPT = 204;\\n    uint256 internal constant CALLER_NOT_VAULT = 205;\\n    uint256 internal constant UNINITIALIZED = 206;\\n    uint256 internal constant BPT_IN_MAX_AMOUNT = 207;\\n    uint256 internal constant BPT_OUT_MIN_AMOUNT = 208;\\n    uint256 internal constant EXPIRED_PERMIT = 209;\\n\\n    // Pools\\n    uint256 internal constant MIN_AMP = 300;\\n    uint256 internal constant MAX_AMP = 301;\\n    uint256 internal constant MIN_WEIGHT = 302;\\n    uint256 internal constant MAX_STABLE_TOKENS = 303;\\n    uint256 internal constant MAX_IN_RATIO = 304;\\n    uint256 internal constant MAX_OUT_RATIO = 305;\\n    uint256 internal constant MIN_BPT_IN_FOR_TOKEN_OUT = 306;\\n    uint256 internal constant MAX_OUT_BPT_FOR_TOKEN_IN = 307;\\n    uint256 internal constant NORMALIZED_WEIGHT_INVARIANT = 308;\\n    uint256 internal constant INVALID_TOKEN = 309;\\n    uint256 internal constant UNHANDLED_JOIN_KIND = 310;\\n    uint256 internal constant ZERO_INVARIANT = 311;\\n\\n    // Lib\\n    uint256 internal constant REENTRANCY = 400;\\n    uint256 internal constant SENDER_NOT_ALLOWED = 401;\\n    uint256 internal constant PAUSED = 402;\\n    uint256 internal constant PAUSE_WINDOW_EXPIRED = 403;\\n    uint256 internal constant MAX_PAUSE_WINDOW_DURATION = 404;\\n    uint256 internal constant MAX_BUFFER_PERIOD_DURATION = 405;\\n    uint256 internal constant INSUFFICIENT_BALANCE = 406;\\n    uint256 internal constant INSUFFICIENT_ALLOWANCE = 407;\\n    uint256 internal constant ERC20_TRANSFER_FROM_ZERO_ADDRESS = 408;\\n    uint256 internal constant ERC20_TRANSFER_TO_ZERO_ADDRESS = 409;\\n    uint256 internal constant ERC20_MINT_TO_ZERO_ADDRESS = 410;\\n    uint256 internal constant ERC20_BURN_FROM_ZERO_ADDRESS = 411;\\n    uint256 internal constant ERC20_APPROVE_FROM_ZERO_ADDRESS = 412;\\n    uint256 internal constant ERC20_APPROVE_TO_ZERO_ADDRESS = 413;\\n    uint256 internal constant ERC20_TRANSFER_EXCEEDS_ALLOWANCE = 414;\\n    uint256 internal constant ERC20_DECREASED_ALLOWANCE_BELOW_ZERO = 415;\\n    uint256 internal constant ERC20_TRANSFER_EXCEEDS_BALANCE = 416;\\n    uint256 internal constant ERC20_BURN_EXCEEDS_ALLOWANCE = 417;\\n    uint256 internal constant SAFE_ERC20_CALL_FAILED = 418;\\n    uint256 internal constant ADDRESS_INSUFFICIENT_BALANCE = 419;\\n    uint256 internal constant ADDRESS_CANNOT_SEND_VALUE = 420;\\n    uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_INT256 = 421;\\n    uint256 internal constant GRANT_SENDER_NOT_ADMIN = 422;\\n    uint256 internal constant REVOKE_SENDER_NOT_ADMIN = 423;\\n    uint256 internal constant RENOUNCE_SENDER_NOT_ALLOWED = 424;\\n    uint256 internal constant BUFFER_PERIOD_EXPIRED = 425;\\n\\n    // Vault\\n    uint256 internal constant INVALID_POOL_ID = 500;\\n    uint256 internal constant CALLER_NOT_POOL = 501;\\n    uint256 internal constant SENDER_NOT_ASSET_MANAGER = 502;\\n    uint256 internal constant USER_DOESNT_ALLOW_RELAYER = 503;\\n    uint256 internal constant INVALID_SIGNATURE = 504;\\n    uint256 internal constant EXIT_BELOW_MIN = 505;\\n    uint256 internal constant JOIN_ABOVE_MAX = 506;\\n    uint256 internal constant SWAP_LIMIT = 507;\\n    uint256 internal constant SWAP_DEADLINE = 508;\\n    uint256 internal constant CANNOT_SWAP_SAME_TOKEN = 509;\\n    uint256 internal constant UNKNOWN_AMOUNT_IN_FIRST_SWAP = 510;\\n    uint256 internal constant MALCONSTRUCTED_MULTIHOP_SWAP = 511;\\n    uint256 internal constant INTERNAL_BALANCE_OVERFLOW = 512;\\n    uint256 internal constant INSUFFICIENT_INTERNAL_BALANCE = 513;\\n    uint256 internal constant INVALID_ETH_INTERNAL_BALANCE = 514;\\n    uint256 internal constant INVALID_POST_LOAN_BALANCE = 515;\\n    uint256 internal constant INSUFFICIENT_ETH = 516;\\n    uint256 internal constant UNALLOCATED_ETH = 517;\\n    uint256 internal constant ETH_TRANSFER = 518;\\n    uint256 internal constant CANNOT_USE_ETH_SENTINEL = 519;\\n    uint256 internal constant TOKENS_MISMATCH = 520;\\n    uint256 internal constant TOKEN_NOT_REGISTERED = 521;\\n    uint256 internal constant TOKEN_ALREADY_REGISTERED = 522;\\n    uint256 internal constant TOKENS_ALREADY_SET = 523;\\n    uint256 internal constant TOKENS_LENGTH_MUST_BE_2 = 524;\\n    uint256 internal constant NONZERO_TOKEN_BALANCE = 525;\\n    uint256 internal constant BALANCE_TOTAL_OVERFLOW = 526;\\n    uint256 internal constant POOL_NO_TOKENS = 527;\\n    uint256 internal constant INSUFFICIENT_FLASH_LOAN_BALANCE = 528;\\n\\n    // Fees\\n    uint256 internal constant SWAP_FEE_PERCENTAGE_TOO_HIGH = 600;\\n    uint256 internal constant FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH = 601;\\n    uint256 internal constant INSUFFICIENT_FLASH_LOAN_FEES = 602;\\n}\\n\",\"keccak256\":\"0xd55b221ce0812144b0f9e05efd305916a2d4d2f8fbce964175e3f7a9060d145c\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/lib/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;\\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\",\"keccak256\":\"0xfd687ced203d2c6da8189792e1719a5182faf45956129388b231ee76740b99a6\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/lib/helpers/InputHelpers.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;\\n\\nimport \\\"../openzeppelin/IERC20.sol\\\";\\n\\nimport \\\"./BalancerErrors.sol\\\";\\n\\nimport \\\"../../vault/interfaces/IAsset.sol\\\";\\n\\nlibrary InputHelpers {\\n    function ensureInputLengthMatch(uint256 a, uint256 b) internal pure {\\n        _require(a == b, Errors.INPUT_LENGTH_MISMATCH);\\n    }\\n\\n    function ensureInputLengthMatch(\\n        uint256 a,\\n        uint256 b,\\n        uint256 c\\n    ) internal pure {\\n        _require(a == b && b == c, Errors.INPUT_LENGTH_MISMATCH);\\n    }\\n\\n    function ensureArrayIsSorted(IAsset[] memory array) internal pure {\\n        address[] memory addressArray;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            addressArray := array\\n        }\\n        ensureArrayIsSorted(addressArray);\\n    }\\n\\n    function ensureArrayIsSorted(IERC20[] memory array) internal pure {\\n        address[] memory addressArray;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            addressArray := array\\n        }\\n        ensureArrayIsSorted(addressArray);\\n    }\\n\\n    function ensureArrayIsSorted(address[] memory array) internal pure {\\n        if (array.length < 2) {\\n            return;\\n        }\\n\\n        address previous = array[0];\\n        for (uint256 i = 1; i < array.length; ++i) {\\n            address current = array[i];\\n            _require(previous < current, Errors.UNSORTED_ARRAY);\\n            previous = current;\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xd58eb6851269729d3ea0d739f812c67c3e750b046ef1653ae12134e668925d28\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/lib/helpers/TemporarilyPausable.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;\\n\\nimport \\\"./BalancerErrors.sol\\\";\\n\\n/**\\n * @dev Allows for a contract to be paused during an initial period after deployment, disabling functionality. Can be\\n * used as an emergency switch in case a security vulnerability or threat is identified.\\n *\\n * The contract can only be paused during the Pause Window, a period that starts at deployment. It can also be\\n * unpaused and repaused any number of times during this period. This is intended to serve as a safety measure: it lets\\n * system managers react quickly to potentially dangerous situations, knowing that this action is reversible if careful\\n * analysis later determines there was a false alarm.\\n *\\n * If the contract is paused when the Pause Window finishes, it will remain in the paused state through an additional\\n * Buffer Period, after which it will be automatically unpaused forever. This is to ensure there is always enough time\\n * to react to an emergency, even if the threat is discovered shortly before the Pause Window expires.\\n *\\n * Note that since the contract can only be paused within the Pause Window, unpausing during the Buffer Period is\\n * irreversible.\\n */\\nabstract contract TemporarilyPausable {\\n    // The Pause Window and Buffer Period are timestamp-based: they should not be relied upon for sub-minute accuracy.\\n    // solhint-disable not-rely-on-time\\n\\n    uint256 private constant _MAX_PAUSE_WINDOW_DURATION = 90 days;\\n    uint256 private constant _MAX_BUFFER_PERIOD_DURATION = 30 days;\\n\\n    uint256 private immutable _pauseWindowEndTime;\\n    uint256 private immutable _bufferPeriodEndTime;\\n\\n    bool private _paused;\\n\\n    event PausedStateChanged(bool paused);\\n\\n    constructor(uint256 pauseWindowDuration, uint256 bufferPeriodDuration) {\\n        _require(pauseWindowDuration <= _MAX_PAUSE_WINDOW_DURATION, Errors.MAX_PAUSE_WINDOW_DURATION);\\n        _require(bufferPeriodDuration <= _MAX_BUFFER_PERIOD_DURATION, Errors.MAX_BUFFER_PERIOD_DURATION);\\n\\n        uint256 pauseWindowEndTime = block.timestamp + pauseWindowDuration;\\n\\n        _pauseWindowEndTime = pauseWindowEndTime;\\n        _bufferPeriodEndTime = pauseWindowEndTime + bufferPeriodDuration;\\n    }\\n\\n    /**\\n     * @dev Reverts if the contract is paused.\\n     */\\n    modifier whenNotPaused() {\\n        _ensureNotPaused();\\n        _;\\n    }\\n\\n    /**\\n     * @dev Returns the current contract pause status, as well as the end times of the Pause Window and Buffer\\n     * Period.\\n     */\\n    function getPausedState()\\n        external\\n        view\\n        returns (\\n            bool paused,\\n            uint256 pauseWindowEndTime,\\n            uint256 bufferPeriodEndTime\\n        )\\n    {\\n        paused = !_isNotPaused();\\n        pauseWindowEndTime = _getPauseWindowEndTime();\\n        bufferPeriodEndTime = _getBufferPeriodEndTime();\\n    }\\n\\n    /**\\n     * @dev Sets the pause state to `paused`. The contract can only be paused until the end of the Pause Window, and\\n     * unpaused until the end of the Buffer Period.\\n     *\\n     * Once the Buffer Period expires, this function reverts unconditionally.\\n     */\\n    function _setPaused(bool paused) internal {\\n        if (paused) {\\n            _require(block.timestamp < _getPauseWindowEndTime(), Errors.PAUSE_WINDOW_EXPIRED);\\n        } else {\\n            _require(block.timestamp < _getBufferPeriodEndTime(), Errors.BUFFER_PERIOD_EXPIRED);\\n        }\\n\\n        _paused = paused;\\n        emit PausedStateChanged(paused);\\n    }\\n\\n    /**\\n     * @dev Reverts if the contract is paused.\\n     */\\n    function _ensureNotPaused() internal view {\\n        _require(_isNotPaused(), Errors.PAUSED);\\n    }\\n\\n    /**\\n     * @dev Returns true if the contract is unpaused.\\n     *\\n     * Once the Buffer Period expires, the gas cost of calling this function is reduced dramatically, as storage is no\\n     * longer accessed.\\n     */\\n    function _isNotPaused() internal view returns (bool) {\\n        // After the Buffer Period, the (inexpensive) timestamp check short-circuits the storage access.\\n        return block.timestamp > _getBufferPeriodEndTime() || !_paused;\\n    }\\n\\n    // These getters lead to reduced bytecode size by inlining the immutable variables in a single place.\\n\\n    function _getPauseWindowEndTime() private view returns (uint256) {\\n        return _pauseWindowEndTime;\\n    }\\n\\n    function _getBufferPeriodEndTime() private view returns (uint256) {\\n        return _bufferPeriodEndTime;\\n    }\\n}\\n\",\"keccak256\":\"0x62ce7916f3c54325cc982b261747de5a1ab411de571af003d746f770969a1e5e\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/lib/math/FixedPoint.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;\\n\\nimport \\\"./LogExpMath.sol\\\";\\nimport \\\"../helpers/BalancerErrors.sol\\\";\\n\\n/* solhint-disable private-vars-leading-underscore */\\n\\nlibrary FixedPoint {\\n    uint256 internal constant ONE = 1e18; // 18 decimal places\\n    uint256 internal constant MAX_POW_RELATIVE_ERROR = 10000; // 10^(-14)\\n\\n    // Minimum base for the power function when the exponent is 'free' (larger than ONE).\\n    uint256 internal constant MIN_POW_BASE_FREE_EXPONENT = 0.7e18;\\n\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // Fixed Point addition is the same as regular checked addition\\n\\n        uint256 c = a + b;\\n        _require(c >= a, Errors.ADD_OVERFLOW);\\n        return c;\\n    }\\n\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // Fixed Point addition is the same as regular checked addition\\n\\n        _require(b <= a, Errors.SUB_OVERFLOW);\\n        uint256 c = a - b;\\n        return c;\\n    }\\n\\n    function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 product = a * b;\\n        _require(a == 0 || product / a == b, Errors.MUL_OVERFLOW);\\n\\n        return product / ONE;\\n    }\\n\\n    function mulUp(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 product = a * b;\\n        _require(a == 0 || product / a == b, Errors.MUL_OVERFLOW);\\n\\n        if (product == 0) {\\n            return 0;\\n        } else {\\n            // The traditional divUp formula is:\\n            // divUp(x, y) := (x + y - 1) / y\\n            // To avoid intermediate overflow in the addition, we distribute the division and get:\\n            // divUp(x, y) := (x - 1) / y + 1\\n            // Note that this requires x != 0, which we already tested for.\\n\\n            return ((product - 1) / ONE) + 1;\\n        }\\n    }\\n\\n    function divDown(uint256 a, uint256 b) internal pure returns (uint256) {\\n        _require(b != 0, Errors.ZERO_DIVISION);\\n\\n        if (a == 0) {\\n            return 0;\\n        } else {\\n            uint256 aInflated = a * ONE;\\n            _require(aInflated / a == ONE, Errors.DIV_INTERNAL); // mul overflow\\n\\n            return aInflated / b;\\n        }\\n    }\\n\\n    function divUp(uint256 a, uint256 b) internal pure returns (uint256) {\\n        _require(b != 0, Errors.ZERO_DIVISION);\\n\\n        if (a == 0) {\\n            return 0;\\n        } else {\\n            uint256 aInflated = a * ONE;\\n            _require(aInflated / a == ONE, Errors.DIV_INTERNAL); // mul overflow\\n\\n            // The traditional divUp formula is:\\n            // divUp(x, y) := (x + y - 1) / y\\n            // To avoid intermediate overflow in the addition, we distribute the division and get:\\n            // divUp(x, y) := (x - 1) / y + 1\\n            // Note that this requires x != 0, which we already tested for.\\n\\n            return ((aInflated - 1) / b) + 1;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns x^y, assuming both are fixed point numbers, rounding down. The result is guaranteed to not be above\\n     * the true value (that is, the error function expected - actual is always positive).\\n     */\\n    function powDown(uint256 x, uint256 y) internal pure returns (uint256) {\\n        uint256 raw = LogExpMath.pow(x, y);\\n        uint256 maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), 1);\\n\\n        if (raw < maxError) {\\n            return 0;\\n        } else {\\n            return sub(raw, maxError);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns x^y, assuming both are fixed point numbers, rounding up. The result is guaranteed to not be below\\n     * the true value (that is, the error function expected - actual is always negative).\\n     */\\n    function powUp(uint256 x, uint256 y) internal pure returns (uint256) {\\n        uint256 raw = LogExpMath.pow(x, y);\\n        uint256 maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), 1);\\n\\n        return add(raw, maxError);\\n    }\\n\\n    /**\\n     * @dev Returns the complement of a value (1 - x), capped to 0 if x is larger than 1.\\n     *\\n     * Useful when computing the complement for values with some level of relative error, as it strips this error and\\n     * prevents intermediate negative values.\\n     */\\n    function complement(uint256 x) internal pure returns (uint256) {\\n        return (x < ONE) ? (ONE - x) : 0;\\n    }\\n}\\n\",\"keccak256\":\"0x38720507bb6c838df83953d1ffa88b97d0e06baefa0e3e387303cb8a090a49f5\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/lib/math/LogExpMath.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 internal License for more details.\\n\\n// You should have received a copy of the GNU General internal License\\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../helpers/BalancerErrors.sol\\\";\\n\\n/* solhint-disable */\\n\\n/**\\n * @dev Exponentiation and logarithm functions for 18 decimal fixed point numbers (both base and exponent/argument).\\n *\\n * Exponentiation and logarithm with arbitrary bases (x^y and log_x(y)) are implemented by conversion to natural\\n * exponentiation and logarithm (where the base is Euler's number).\\n *\\n * @author Fernando Martinelli - @fernandomartinelli\\n * @author Sergio Yuhjtman - @sergioyuhjtman\\n * @author Daniel Fernandez - @dmf7z\\n */\\nlibrary LogExpMath {\\n    // All fixed point multiplications and divisions are inlined. This means we need to divide by ONE when multiplying\\n    // two numbers, and multiply by ONE when dividing them.\\n\\n    // All arguments and return values are 18 decimal fixed point numbers.\\n    int256 constant ONE_18 = 1e18;\\n\\n    // Internally, intermediate values are computed with higher precision as 20 decimal fixed point numbers, and in the\\n    // case of ln36, 36 decimals.\\n    int256 constant ONE_20 = 1e20;\\n    int256 constant ONE_36 = 1e36;\\n\\n    // The domain of natural exponentiation is bound by the word size and number of decimals used.\\n    //\\n    // Because internally the result will be stored using 20 decimals, the largest possible result is\\n    // (2^255 - 1) / 10^20, which makes the largest exponent ln((2^255 - 1) / 10^20) = 130.700829182905140221.\\n    // The smallest possible result is 10^(-18), which makes largest negative argument\\n    // ln(10^(-18)) = -41.446531673892822312.\\n    // We use 130.0 and -41.0 to have some safety margin.\\n    int256 constant MAX_NATURAL_EXPONENT = 130e18;\\n    int256 constant MIN_NATURAL_EXPONENT = -41e18;\\n\\n    // Bounds for ln_36's argument. Both ln(0.9) and ln(1.1) can be represented with 36 decimal places in a fixed point\\n    // 256 bit integer.\\n    int256 constant LN_36_LOWER_BOUND = ONE_18 - 1e17;\\n    int256 constant LN_36_UPPER_BOUND = ONE_18 + 1e17;\\n\\n    uint256 constant MILD_EXPONENT_BOUND = 2**254 / uint256(ONE_20);\\n\\n    // 18 decimal constants\\n    int256 constant x0 = 128000000000000000000; // 2\\u02c67\\n    int256 constant a0 = 38877084059945950922200000000000000000000000000000000000; // e\\u02c6(x0) (no decimals)\\n    int256 constant x1 = 64000000000000000000; // 2\\u02c66\\n    int256 constant a1 = 6235149080811616882910000000; // e\\u02c6(x1) (no decimals)\\n\\n    // 20 decimal constants\\n    int256 constant x2 = 3200000000000000000000; // 2\\u02c65\\n    int256 constant a2 = 7896296018268069516100000000000000; // e\\u02c6(x2)\\n    int256 constant x3 = 1600000000000000000000; // 2\\u02c64\\n    int256 constant a3 = 888611052050787263676000000; // e\\u02c6(x3)\\n    int256 constant x4 = 800000000000000000000; // 2\\u02c63\\n    int256 constant a4 = 298095798704172827474000; // e\\u02c6(x4)\\n    int256 constant x5 = 400000000000000000000; // 2\\u02c62\\n    int256 constant a5 = 5459815003314423907810; // e\\u02c6(x5)\\n    int256 constant x6 = 200000000000000000000; // 2\\u02c61\\n    int256 constant a6 = 738905609893065022723; // e\\u02c6(x6)\\n    int256 constant x7 = 100000000000000000000; // 2\\u02c60\\n    int256 constant a7 = 271828182845904523536; // e\\u02c6(x7)\\n    int256 constant x8 = 50000000000000000000; // 2\\u02c6-1\\n    int256 constant a8 = 164872127070012814685; // e\\u02c6(x8)\\n    int256 constant x9 = 25000000000000000000; // 2\\u02c6-2\\n    int256 constant a9 = 128402541668774148407; // e\\u02c6(x9)\\n    int256 constant x10 = 12500000000000000000; // 2\\u02c6-3\\n    int256 constant a10 = 113314845306682631683; // e\\u02c6(x10)\\n    int256 constant x11 = 6250000000000000000; // 2\\u02c6-4\\n    int256 constant a11 = 106449445891785942956; // e\\u02c6(x11)\\n\\n    /**\\n     * @dev Exponentiation (x^y) with unsigned 18 decimal fixed point base and exponent.\\n     *\\n     * Reverts if ln(x) * y is smaller than `MIN_NATURAL_EXPONENT`, or larger than `MAX_NATURAL_EXPONENT`.\\n     */\\n    function pow(uint256 x, uint256 y) internal pure returns (uint256) {\\n        if (y == 0) {\\n            // We solve the 0^0 indetermination by making it equal one.\\n            return uint256(ONE_18);\\n        }\\n\\n        if (x == 0) {\\n            return 0;\\n        }\\n\\n        // Instead of computing x^y directly, we instead rely on the properties of logarithms and exponentiation to\\n        // arrive at that result. In particular, exp(ln(x)) = x, and ln(x^y) = y * ln(x). This means\\n        // x^y = exp(y * ln(x)).\\n\\n        // The ln function takes a signed value, so we need to make sure x fits in the signed 256 bit range.\\n        _require(x < 2**255, Errors.X_OUT_OF_BOUNDS);\\n        int256 x_int256 = int256(x);\\n\\n        // We will compute y * ln(x) in a single step. Depending on the value of x, we can either use ln or ln_36. In\\n        // both cases, we leave the division by ONE_18 (due to fixed point multiplication) to the end.\\n\\n        // This prevents y * ln(x) from overflowing, and at the same time guarantees y fits in the signed 256 bit range.\\n        _require(y < MILD_EXPONENT_BOUND, Errors.Y_OUT_OF_BOUNDS);\\n        int256 y_int256 = int256(y);\\n\\n        int256 logx_times_y;\\n        if (LN_36_LOWER_BOUND < x_int256 && x_int256 < LN_36_UPPER_BOUND) {\\n            int256 ln_36_x = ln_36(x_int256);\\n\\n            // ln_36_x has 36 decimal places, so multiplying by y_int256 isn't as straightforward, since we can't just\\n            // bring y_int256 to 36 decimal places, as it might overflow. Instead, we perform two 18 decimal\\n            // multiplications and add the results: one with the first 18 decimals of ln_36_x, and one with the\\n            // (downscaled) last 18 decimals.\\n            logx_times_y = ((ln_36_x / ONE_18) * y_int256 + ((ln_36_x % ONE_18) * y_int256) / ONE_18);\\n        } else {\\n            logx_times_y = ln(x_int256) * y_int256;\\n        }\\n        logx_times_y /= ONE_18;\\n\\n        // Finally, we compute exp(y * ln(x)) to arrive at x^y\\n        _require(\\n            MIN_NATURAL_EXPONENT <= logx_times_y && logx_times_y <= MAX_NATURAL_EXPONENT,\\n            Errors.PRODUCT_OUT_OF_BOUNDS\\n        );\\n\\n        return uint256(exp(logx_times_y));\\n    }\\n\\n    /**\\n     * @dev Natural exponentiaton (e^x) with signed 18 decimal fixed point exponent.\\n     *\\n     * Reverts if `x` is smaller than MIN_NATURAL_EXPONENT, or larger than `MAX_NATURAL_EXPONENT`.\\n     */\\n    function exp(int256 x) internal pure returns (int256) {\\n        _require(x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT, Errors.INVALID_EXPONENT);\\n\\n        if (x < 0) {\\n            // We only handle positive exponents: e^(-x) is computed as 1 / e^x. We can safely make x positive since it\\n            // fits in the signed 256 bit range (as it is larger than MIN_NATURAL_EXPONENT).\\n            // Fixed point division requires multiplying by ONE_18.\\n            return ((ONE_18 * ONE_18) / exp(-x));\\n        }\\n\\n        // First, we use the fact that e^(x+y) = e^x * e^y to decompose x into a sum of powers of two, which we call x_n,\\n        // where x_n == 2^(7 - n), and e^x_n = a_n has been precomputed. We choose the first x_n, x0, to equal 2^7\\n        // because all larger powers are larger than MAX_NATURAL_EXPONENT, and therefore not present in the\\n        // decomposition.\\n        // At the end of this process we will have the product of all e^x_n = a_n that apply, and the remainder of this\\n        // decomposition, which will be lower than the smallest x_n.\\n        // exp(x) = k_0 * a_0 * k_1 * a_1 * ... + k_n * a_n * exp(remainder), where each k_n equals either 0 or 1.\\n        // We mutate x by subtracting x_n, making it the remainder of the decomposition.\\n\\n        // The first two a_n (e^(2^7) and e^(2^6)) are too large if stored as 18 decimal numbers, and could cause\\n        // intermediate overflows. Instead we store them as plain integers, with 0 decimals.\\n        // Additionally, x0 + x1 is larger than MAX_NATURAL_EXPONENT, which means they will not both be present in the\\n        // decomposition.\\n\\n        // For each x_n, we test if that term is present in the decomposition (if x is larger than it), and if so deduct\\n        // it and compute the accumulated product.\\n\\n        int256 firstAN;\\n        if (x >= x0) {\\n            x -= x0;\\n            firstAN = a0;\\n        } else if (x >= x1) {\\n            x -= x1;\\n            firstAN = a1;\\n        } else {\\n            firstAN = 1; // One with no decimal places\\n        }\\n\\n        // We now transform x into a 20 decimal fixed point number, to have enhanced precision when computing the\\n        // smaller terms.\\n        x *= 100;\\n\\n        // `product` is the accumulated product of all a_n (except a0 and a1), which starts at 20 decimal fixed point\\n        // one. Recall that fixed point multiplication requires dviding by ONE_20.\\n        int256 product = ONE_20;\\n\\n        if (x >= x2) {\\n            x -= x2;\\n            product = (product * a2) / ONE_20;\\n        }\\n        if (x >= x3) {\\n            x -= x3;\\n            product = (product * a3) / ONE_20;\\n        }\\n        if (x >= x4) {\\n            x -= x4;\\n            product = (product * a4) / ONE_20;\\n        }\\n        if (x >= x5) {\\n            x -= x5;\\n            product = (product * a5) / ONE_20;\\n        }\\n        if (x >= x6) {\\n            x -= x6;\\n            product = (product * a6) / ONE_20;\\n        }\\n        if (x >= x7) {\\n            x -= x7;\\n            product = (product * a7) / ONE_20;\\n        }\\n        if (x >= x8) {\\n            x -= x8;\\n            product = (product * a8) / ONE_20;\\n        }\\n        if (x >= x9) {\\n            x -= x9;\\n            product = (product * a9) / ONE_20;\\n        }\\n\\n        // x10 and x11 are unnecessary here since we have high enough precision already.\\n\\n        // Now we need to compute e^x, where x is small (in particular, it is smaller than x9). We use the Taylor series\\n        // expansion for e^x: 1 + x + (x^2 / 2!) + (x^3 / 3!) + ... + (x^n / n!).\\n\\n        int256 seriesSum = ONE_20; // The initial one in the sum, with 20 decimal places.\\n        int256 term; // Each term in the sum, where the nth term is (x^n / n!).\\n\\n        // The first term is simply x.\\n        term = x;\\n        seriesSum += term;\\n\\n        // Each term (x^n / n!) equals the previous one times x, divided by n. Since x is a fixed point number,\\n        // multiplying by it requires dividing by ONE_20, but dividing by the non-fixed point n values does not.\\n\\n        term = ((term * x) / ONE_20) / 2;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 3;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 4;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 5;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 6;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 7;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 8;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 9;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 10;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 11;\\n        seriesSum += term;\\n\\n        term = ((term * x) / ONE_20) / 12;\\n        seriesSum += term;\\n\\n        // 12 Taylor terms are sufficient for 18 decimal precision.\\n\\n        // We now have the first a_n (with no decimals), and the product of all other a_n present, and the Taylor\\n        // approximation of the exponention of the remainder (both with 20 decimals). All that remains is to multiply\\n        // all three (one 20 decimal fixed point multiplication, dividing by ONE_20, and one integer multiplication),\\n        // and then drop two digits to return an 18 decimal value.\\n\\n        return (((product * seriesSum) / ONE_20) * firstAN) / 100;\\n    }\\n\\n    /**\\n     * @dev Natural logarithm (ln(a)) with signed 18 decimal fixed point argument.\\n     */\\n    function ln(int256 a) internal pure returns (int256) {\\n        // The real natural logarithm is not defined for negative numbers or zero.\\n        _require(a > 0, Errors.OUT_OF_BOUNDS);\\n\\n        if (a < ONE_18) {\\n            // Since ln(a^k) = k * ln(a), we can compute ln(a) as ln(a) = ln((1/a)^(-1)) = - ln((1/a)). If a is less\\n            // than one, 1/a will be greater than one, and this if statement will not be entered in the recursive call.\\n            // Fixed point division requires multiplying by ONE_18.\\n            return (-ln((ONE_18 * ONE_18) / a));\\n        }\\n\\n        // First, we use the fact that ln^(a * b) = ln(a) + ln(b) to decompose ln(a) into a sum of powers of two, which\\n        // we call x_n, where x_n == 2^(7 - n), which are the natural logarithm of precomputed quantities a_n (that is,\\n        // ln(a_n) = x_n). We choose the first x_n, x0, to equal 2^7 because the exponential of all larger powers cannot\\n        // be represented as 18 fixed point decimal numbers in 256 bits, and are therefore larger than a.\\n        // At the end of this process we will have the sum of all x_n = ln(a_n) that apply, and the remainder of this\\n        // decomposition, which will be lower than the smallest a_n.\\n        // ln(a) = k_0 * x_0 + k_1 * x_1 + ... + k_n * x_n + ln(remainder), where each k_n equals either 0 or 1.\\n        // We mutate a by subtracting a_n, making it the remainder of the decomposition.\\n\\n        // For reasons related to how `exp` works, the first two a_n (e^(2^7) and e^(2^6)) are not stored as fixed point\\n        // numbers with 18 decimals, but instead as plain integers with 0 decimals, so we need to multiply them by\\n        // ONE_18 to convert them to fixed point.\\n        // For each a_n, we test if that term is present in the decomposition (if a is larger than it), and if so divide\\n        // by it and compute the accumulated sum.\\n\\n        int256 sum = 0;\\n        if (a >= a0 * ONE_18) {\\n            a /= a0; // Integer, not fixed point division\\n            sum += x0;\\n        }\\n\\n        if (a >= a1 * ONE_18) {\\n            a /= a1; // Integer, not fixed point division\\n            sum += x1;\\n        }\\n\\n        // All other a_n and x_n are stored as 20 digit fixed point numbers, so we convert the sum and a to this format.\\n        sum *= 100;\\n        a *= 100;\\n\\n        // Because further a_n are  20 digit fixed point numbers, we multiply by ONE_20 when dividing by them.\\n\\n        if (a >= a2) {\\n            a = (a * ONE_20) / a2;\\n            sum += x2;\\n        }\\n\\n        if (a >= a3) {\\n            a = (a * ONE_20) / a3;\\n            sum += x3;\\n        }\\n\\n        if (a >= a4) {\\n            a = (a * ONE_20) / a4;\\n            sum += x4;\\n        }\\n\\n        if (a >= a5) {\\n            a = (a * ONE_20) / a5;\\n            sum += x5;\\n        }\\n\\n        if (a >= a6) {\\n            a = (a * ONE_20) / a6;\\n            sum += x6;\\n        }\\n\\n        if (a >= a7) {\\n            a = (a * ONE_20) / a7;\\n            sum += x7;\\n        }\\n\\n        if (a >= a8) {\\n            a = (a * ONE_20) / a8;\\n            sum += x8;\\n        }\\n\\n        if (a >= a9) {\\n            a = (a * ONE_20) / a9;\\n            sum += x9;\\n        }\\n\\n        if (a >= a10) {\\n            a = (a * ONE_20) / a10;\\n            sum += x10;\\n        }\\n\\n        if (a >= a11) {\\n            a = (a * ONE_20) / a11;\\n            sum += x11;\\n        }\\n\\n        // a is now a small number (smaller than a_11, which roughly equals 1.06). This means we can use a Taylor series\\n        // that converges rapidly for values of `a` close to one - the same one used in ln_36.\\n        // Let z = (a - 1) / (a + 1).\\n        // ln(a) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1))\\n\\n        // Recall that 20 digit fixed point division requires multiplying by ONE_20, and multiplication requires\\n        // division by ONE_20.\\n        int256 z = ((a - ONE_20) * ONE_20) / (a + ONE_20);\\n        int256 z_squared = (z * z) / ONE_20;\\n\\n        // num is the numerator of the series: the z^(2 * n + 1) term\\n        int256 num = z;\\n\\n        // seriesSum holds the accumulated sum of each term in the series, starting with the initial z\\n        int256 seriesSum = num;\\n\\n        // In each step, the numerator is multiplied by z^2\\n        num = (num * z_squared) / ONE_20;\\n        seriesSum += num / 3;\\n\\n        num = (num * z_squared) / ONE_20;\\n        seriesSum += num / 5;\\n\\n        num = (num * z_squared) / ONE_20;\\n        seriesSum += num / 7;\\n\\n        num = (num * z_squared) / ONE_20;\\n        seriesSum += num / 9;\\n\\n        num = (num * z_squared) / ONE_20;\\n        seriesSum += num / 11;\\n\\n        // 6 Taylor terms are sufficient for 36 decimal precision.\\n\\n        // Finally, we multiply by 2 (non fixed point) to compute ln(remainder)\\n        seriesSum *= 2;\\n\\n        // We now have the sum of all x_n present, and the Taylor approximation of the logarithm of the remainder (both\\n        // with 20 decimals). All that remains is to sum these two, and then drop two digits to return a 18 decimal\\n        // value.\\n\\n        return (sum + seriesSum) / 100;\\n    }\\n\\n    /**\\n     * @dev Logarithm (log(arg, base), with signed 18 decimal fixed point base and argument argument.\\n     */\\n    function log(int256 arg, int256 base) internal pure returns (int256) {\\n        // This performs a simple base change: log(arg, base) = ln(arg) / ln(base).\\n\\n        // Both logBase and logArg are computed as 36 decimal fixed point numbers, either by using ln_36, or by\\n        // upscaling.\\n\\n        int256 logBase;\\n        if (LN_36_LOWER_BOUND < base && base < LN_36_UPPER_BOUND) {\\n            logBase = ln_36(base);\\n        } else {\\n            logBase = ln(base) * ONE_18;\\n        }\\n\\n        int256 logArg;\\n        if (LN_36_LOWER_BOUND < arg && arg < LN_36_UPPER_BOUND) {\\n            logArg = ln_36(arg);\\n        } else {\\n            logArg = ln(arg) * ONE_18;\\n        }\\n\\n        // When dividing, we multiply by ONE_18 to arrive at a result with 18 decimal places\\n        return (logArg * ONE_18) / logBase;\\n    }\\n\\n    /**\\n     * @dev High precision (36 decimal places) natural logarithm (ln(x)) with signed 18 decimal fixed point argument,\\n     * for x close to one.\\n     *\\n     * Should only be used if x is between LN_36_LOWER_BOUND and LN_36_UPPER_BOUND.\\n     */\\n    function ln_36(int256 x) private pure returns (int256) {\\n        // Since ln(1) = 0, a value of x close to one will yield a very small result, which makes using 36 digits\\n        // worthwhile.\\n\\n        // First, we transform x to a 36 digit fixed point value.\\n        x *= ONE_18;\\n\\n        // We will use the following Taylor expansion, which converges very rapidly. Let z = (x - 1) / (x + 1).\\n        // ln(x) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1))\\n\\n        // Recall that 36 digit fixed point division requires multiplying by ONE_36, and multiplication requires\\n        // division by ONE_36.\\n        int256 z = ((x - ONE_36) * ONE_36) / (x + ONE_36);\\n        int256 z_squared = (z * z) / ONE_36;\\n\\n        // num is the numerator of the series: the z^(2 * n + 1) term\\n        int256 num = z;\\n\\n        // seriesSum holds the accumulated sum of each term in the series, starting with the initial z\\n        int256 seriesSum = num;\\n\\n        // In each step, the numerator is multiplied by z^2\\n        num = (num * z_squared) / ONE_36;\\n        seriesSum += num / 3;\\n\\n        num = (num * z_squared) / ONE_36;\\n        seriesSum += num / 5;\\n\\n        num = (num * z_squared) / ONE_36;\\n        seriesSum += num / 7;\\n\\n        num = (num * z_squared) / ONE_36;\\n        seriesSum += num / 9;\\n\\n        num = (num * z_squared) / ONE_36;\\n        seriesSum += num / 11;\\n\\n        num = (num * z_squared) / ONE_36;\\n        seriesSum += num / 13;\\n\\n        num = (num * z_squared) / ONE_36;\\n        seriesSum += num / 15;\\n\\n        // 8 Taylor terms are sufficient for 36 decimal precision.\\n\\n        // All that remains is multiplying by 2 (non fixed point).\\n        return seriesSum * 2;\\n    }\\n}\\n\",\"keccak256\":\"0x828921038b94a51e9408f466af8a31eb4faa533838daaf0ce677211493837a76\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/lib/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../helpers/BalancerErrors.sol\\\";\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow checks.\\n * Adapted from OpenZeppelin's SafeMath library\\n */\\nlibrary Math {\\n    /**\\n     * @dev Returns the addition of two unsigned integers of 256 bits, reverting on overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        _require(c >= a, Errors.ADD_OVERFLOW);\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two signed integers, reverting on overflow.\\n     */\\n    function add(int256 a, int256 b) internal pure returns (int256) {\\n        int256 c = a + b;\\n        _require((b >= 0 && c >= a) || (b < 0 && c < a), Errors.ADD_OVERFLOW);\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers of 256 bits, reverting on overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        _require(b <= a, Errors.SUB_OVERFLOW);\\n        uint256 c = a - b;\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two signed integers, reverting on overflow.\\n     */\\n    function sub(int256 a, int256 b) internal pure returns (int256) {\\n        int256 c = a - b;\\n        _require((b >= 0 && c <= a) || (b < 0 && c > a), Errors.SUB_OVERFLOW);\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the largest of two numbers of 256 bits.\\n     */\\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a >= b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the smallest of two numbers of 256 bits.\\n     */\\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a < b ? a : b;\\n    }\\n\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a * b;\\n        _require(a == 0 || c / a == b, Errors.MUL_OVERFLOW);\\n        return c;\\n    }\\n\\n    function divDown(uint256 a, uint256 b) internal pure returns (uint256) {\\n        _require(b != 0, Errors.ZERO_DIVISION);\\n        return a / b;\\n    }\\n\\n    function divUp(uint256 a, uint256 b) internal pure returns (uint256) {\\n        _require(b != 0, Errors.ZERO_DIVISION);\\n\\n        if (a == 0) {\\n            return 0;\\n        } else {\\n            return 1 + (a - 1) / b;\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x98cf5d1e9b91be5a4315c1aa7bf6480e097113c5f9a9200c92d123bc4ece9ec4\",\"license\":\"MIT\"},\"src.sol/amm/lib/openzeppelin/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        _HASHED_NAME = keccak256(bytes(name));\\n        _HASHED_VERSION = keccak256(bytes(version));\\n        _TYPE_HASH = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view virtual returns (bytes32) {\\n        return keccak256(abi.encode(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION, _getChainId(), address(this)));\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", _domainSeparatorV4(), structHash));\\n    }\\n\\n    function _getChainId() private view returns (uint256 chainId) {\\n        // Silence state mutability warning without generating bytecode.\\n        // See https://github.com/ethereum/solidity/issues/10090#issuecomment-741789128 and\\n        // https://github.com/ethereum/solidity/issues/2691\\n        this;\\n\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly {\\n            chainId := chainid()\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x0cf3ec5d6130aac057e69df14b1ff87baf9c6c2cb13bc545952def004e629ac0\",\"license\":\"MIT\"},\"src.sol/amm/lib/openzeppelin/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../helpers/BalancerErrors.sol\\\";\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./SafeMath.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is IERC20 {\\n    using SafeMath for uint256;\\n\\n    mapping(address => uint256) private _balances;\\n\\n    mapping(address => mapping(address => uint256)) private _allowances;\\n\\n    uint256 private _totalSupply;\\n\\n    string private _name;\\n    string private _symbol;\\n    uint8 private _decimals;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n     * a default value of 18.\\n     *\\n     * To select a different value for {decimals}, use {_setupDecimals}.\\n     *\\n     * All three of these values are immutable: they can only be set once during\\n     * construction.\\n     */\\n    constructor(string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n        _decimals = 18;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev Returns the symbol of the token, usually a shorter version of the\\n     * name.\\n     */\\n    function symbol() public view returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev Returns the number of decimals used to get its user representation.\\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n     * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n     *\\n     * Tokens usually opt for a value of 18, imitating the relationship between\\n     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\\n     * called.\\n     *\\n     * NOTE: This information is only used for _display_ purposes: it in\\n     * no way affects any of the arithmetic of the contract, including\\n     * {IERC20-balanceOf} and {IERC20-transfer}.\\n     */\\n    function decimals() public view returns (uint8) {\\n        return _decimals;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-totalSupply}.\\n     */\\n    function totalSupply() public view override returns (uint256) {\\n        return _totalSupply;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-balanceOf}.\\n     */\\n    function balanceOf(address account) public view override returns (uint256) {\\n        return _balances[account];\\n    }\\n\\n    /**\\n     * @dev See {IERC20-transfer}.\\n     *\\n     * Requirements:\\n     *\\n     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(msg.sender, recipient, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-allowance}.\\n     */\\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n        return _allowances[owner][spender];\\n    }\\n\\n    /**\\n     * @dev See {IERC20-approve}.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(msg.sender, spender, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-transferFrom}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance. This is not\\n     * required by the EIP. See the note at the beginning of {ERC20}.\\n     *\\n     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n        _approve(\\n            sender,\\n            msg.sender,\\n            _allowances[sender][msg.sender].sub(amount, Errors.ERC20_TRANSFER_EXCEEDS_ALLOWANCE)\\n        );\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\\n     *\\n     * This is an alternative to {approve} that can be used as a mitigation for\\n     * problems described in {IERC20-approve}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n     *\\n     * This is an alternative to {approve} that can be used as a mitigation for\\n     * problems described in {IERC20-approve}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     * - `spender` must have allowance for the caller of at least\\n     * `subtractedValue`.\\n     */\\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n        _approve(\\n            msg.sender,\\n            spender,\\n            _allowances[msg.sender][spender].sub(subtractedValue, Errors.ERC20_DECREASED_ALLOWANCE_BELOW_ZERO)\\n        );\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\\n     *\\n     * This is internal function is equivalent to {transfer}, and can be used to\\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\\n     *\\n     * Emits a {Transfer} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) internal virtual {\\n        _require(sender != address(0), Errors.ERC20_TRANSFER_FROM_ZERO_ADDRESS);\\n        _require(recipient != address(0), Errors.ERC20_TRANSFER_TO_ZERO_ADDRESS);\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        _balances[sender] = _balances[sender].sub(amount, Errors.ERC20_TRANSFER_EXCEEDS_BALANCE);\\n        _balances[recipient] = _balances[recipient].add(amount);\\n        emit Transfer(sender, recipient, amount);\\n    }\\n\\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n     * the total supply.\\n     *\\n     * Emits a {Transfer} event with `from` set to the zero address.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     */\\n    function _mint(address account, uint256 amount) internal virtual {\\n        _require(account != address(0), Errors.ERC20_MINT_TO_ZERO_ADDRESS);\\n\\n        _beforeTokenTransfer(address(0), account, amount);\\n\\n        _totalSupply = _totalSupply.add(amount);\\n        _balances[account] = _balances[account].add(amount);\\n        emit Transfer(address(0), account, amount);\\n    }\\n\\n    /**\\n     * @dev Destroys `amount` tokens from `account`, reducing the\\n     * total supply.\\n     *\\n     * Emits a {Transfer} event with `to` set to the zero address.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     * - `account` must have at least `amount` tokens.\\n     */\\n    function _burn(address account, uint256 amount) internal virtual {\\n        _require(account != address(0), Errors.ERC20_BURN_FROM_ZERO_ADDRESS);\\n\\n        _beforeTokenTransfer(account, address(0), amount);\\n\\n        _balances[account] = _balances[account].sub(amount, Errors.ERC20_BURN_EXCEEDS_ALLOWANCE);\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(account, address(0), amount);\\n    }\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n     *\\n     * This internal function is equivalent to `approve`, and can be used to\\n     * e.g. set automatic allowances for certain subsystems, etc.\\n     *\\n     * Emits an {Approval} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `owner` cannot be the zero address.\\n     * - `spender` cannot be the zero address.\\n     */\\n    function _approve(\\n        address owner,\\n        address spender,\\n        uint256 amount\\n    ) internal virtual {\\n        _require(owner != address(0), Errors.ERC20_APPROVE_FROM_ZERO_ADDRESS);\\n        _require(spender != address(0), Errors.ERC20_APPROVE_TO_ZERO_ADDRESS);\\n\\n        _allowances[owner][spender] = amount;\\n        emit Approval(owner, spender, amount);\\n    }\\n\\n    /**\\n     * @dev Sets {decimals} to a value other than the default one of 18.\\n     *\\n     * WARNING: This function should only be called from the constructor. Most\\n     * applications that interact with token contracts will not expect\\n     * {decimals} to ever change, and may work incorrectly if it does.\\n     */\\n    function _setupDecimals(uint8 decimals_) internal {\\n        _decimals = decimals_;\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any transfer of tokens. This includes\\n     * minting and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n     * will be to transferred to `to`.\\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n     * - `from` and `to` are never both zero.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x10a0774f23f09b8617c9c62afe230829175c20be368ff327a7d529e4f7348bcb\",\"license\":\"MIT\"},\"src.sol/amm/lib/openzeppelin/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.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\",\"keccak256\":\"0xd828a935a72a6d182912abba290e4debb8c684c36fd756088f7acb30e0b2bb76\",\"license\":\"MIT\"},\"src.sol/amm/lib/openzeppelin/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n    /**\\n     * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,\\n     * given `owner`'s signed approval.\\n     *\\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n     * ordering also apply here.\\n     *\\n     * Emits an {Approval} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     * - `deadline` must be a timestamp in the future.\\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n     * over the EIP712-formatted function arguments.\\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\\n     *\\n     * For more information on the signature format, see the\\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n     * section].\\n     */\\n    function permit(\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external;\\n\\n    /**\\n     * @dev Returns the current nonce for `owner`. This value must be\\n     * included whenever a signature is generated for {permit}.\\n     *\\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n     * prevents a signature from being used multiple times.\\n     */\\n    function nonces(address owner) external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xffe929ce55ef0cbdcc60eee8bc9375c295757ad13afe3d757646538aa0429ff5\",\"license\":\"MIT\"},\"src.sol/amm/lib/openzeppelin/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../helpers/BalancerErrors.sol\\\";\\n\\n// Based on the ReentrancyGuard library from OpenZeppelin contracts, altered to reduce bytecode size.\\n// Modifier code is inlined by the compiler, which causes its code to appear multiple times in the codebase. By using\\n// private functions, we achieve the same end result with slightly higher runtime gas costs but reduced bytecode size.\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n    // Booleans are more expensive than uint256 or any type that takes up a full\\n    // word because each write operation emits an extra SLOAD to first read the\\n    // slot's contents, replace the bits taken up by the boolean, and then write\\n    // back. This is the compiler's defense against contract upgrades and\\n    // pointer aliasing, and it cannot be disabled.\\n\\n    // The values being non-zero value makes deployment a bit more expensive,\\n    // but in exchange the refund on every call to nonReentrant will be lower in\\n    // amount. Since refunds are capped to a percentage of the total\\n    // transaction's gas, it is best to keep them low in cases like this one, to\\n    // increase the likelihood of the full refund coming into effect.\\n    uint256 private constant _NOT_ENTERED = 1;\\n    uint256 private constant _ENTERED = 2;\\n\\n    uint256 private _status;\\n\\n    constructor() {\\n        _status = _NOT_ENTERED;\\n    }\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     * Calling a `nonReentrant` function from another `nonReentrant`\\n     * function is not supported. It is possible to prevent this from happening\\n     * by making the `nonReentrant` function external, and make it call a\\n     * `private` function that does the actual work.\\n     */\\n    modifier nonReentrant() {\\n        _enterNonReentrant();\\n        _;\\n        _exitNonReentrant();\\n    }\\n\\n    function _enterNonReentrant() private {\\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n        _require(_status != _ENTERED, Errors.REENTRANCY);\\n\\n        // Any calls to nonReentrant after this point will fail\\n        _status = _ENTERED;\\n    }\\n\\n    function _exitNonReentrant() private {\\n        // By storing the original value once again, a refund is triggered (see\\n        // https://eips.ethereum.org/EIPS/eip-2200)\\n        _status = _NOT_ENTERED;\\n    }\\n}\\n\",\"keccak256\":\"0xe055f8c5d34af6e615892acf192c74d2d83784713bd98b2f8e44751f5ffe2bed\",\"license\":\"MIT\"},\"src.sol/amm/lib/openzeppelin/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../helpers/BalancerErrors.sol\\\";\\n\\nimport \\\"./IERC20.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n    function safeTransfer(\\n        IERC20 token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(address(token), abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(\\n        IERC20 token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(address(token), abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     *\\n     * WARNING: `token` is assumed to be a contract: calls to EOAs will *not* revert.\\n     */\\n    function _callOptionalReturn(address token, bytes memory data) private {\\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n        // we're implementing it ourselves.\\n        (bool success, bytes memory returndata) = token.call(data);\\n\\n        // If the low-level call didn't succeed we return whatever was returned from it.\\n        assembly {\\n            if eq(success, 0) {\\n                returndatacopy(0, 0, returndatasize())\\n                revert(0, returndatasize())\\n            }\\n        }\\n\\n        // Finally we check the returndata size is either zero or true - note that this check will always pass for EOAs\\n        _require(returndata.length == 0 || abi.decode(returndata, (bool)), Errors.SAFE_ERC20_CALL_FAILED);\\n    }\\n}\\n\",\"keccak256\":\"0x8db59e0924c72228865dddcadc07e25507809582c50679c8efec6fa737704aed\",\"license\":\"MIT\"},\"src.sol/amm/lib/openzeppelin/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.0;\\n\\nimport \\\"../helpers/BalancerErrors.sol\\\";\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        _require(c >= a, Errors.ADD_OVERFLOW);\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return sub(a, b, Errors.SUB_OVERFLOW);\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, uint256 errorCode) internal pure returns (uint256) {\\n        _require(b <= a, errorCode);\\n        uint256 c = a - b;\\n\\n        return c;\\n    }\\n}\\n\",\"keccak256\":\"0xafe0542eb14932a66ce6280fbe9991130ead5bbcb7836d0a822fc4a59810c100\",\"license\":\"MIT\"},\"src.sol/amm/pools/BalancerPoolToken.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;\\n\\nimport \\\"../lib/math/Math.sol\\\";\\nimport \\\"../lib/openzeppelin/IERC20.sol\\\";\\nimport \\\"../lib/openzeppelin/IERC20Permit.sol\\\";\\nimport \\\"../lib/openzeppelin/EIP712.sol\\\";\\n\\n/**\\n * @title Highly opinionated token implementation\\n * @author Balancer Labs\\n * @dev\\n * - Includes functions to increase and decrease allowance as a workaround\\n *   for the well-known issue with `approve`:\\n *   https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n * - Allows for 'infinite allowance', where an allowance of 0xff..ff is not\\n *   decreased by calls to transferFrom\\n * - Lets a token holder use `transferFrom` to send their own tokens,\\n *   without first setting allowance\\n * - Emits 'Approval' events whenever allowance is changed by `transferFrom`\\n */\\ncontract BalancerPoolToken is IERC20, IERC20Permit, EIP712 {\\n    using Math for uint256;\\n\\n    // State variables\\n\\n    uint8 private constant _DECIMALS = 18;\\n\\n    mapping(address => uint256) private _balance;\\n    mapping(address => mapping(address => uint256)) private _allowance;\\n    uint256 private _totalSupply;\\n\\n    string private _name;\\n    string private _symbol;\\n\\n    mapping(address => uint256) private _nonces;\\n\\n    // solhint-disable-next-line var-name-mixedcase\\n    bytes32 private immutable _PERMIT_TYPE_HASH = keccak256(\\n        \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n    );\\n\\n    // Function declarations\\n\\n    constructor(string memory tokenName, string memory tokenSymbol) EIP712(tokenName, \\\"1\\\") {\\n        _name = tokenName;\\n        _symbol = tokenSymbol;\\n    }\\n\\n    // External functions\\n\\n    function allowance(address owner, address spender) external view override returns (uint256) {\\n        return _allowance[owner][spender];\\n    }\\n\\n    function balanceOf(address account) external view override returns (uint256) {\\n        return _balance[account];\\n    }\\n\\n    function approve(address spender, uint256 amount) external override returns (bool) {\\n        _setAllowance(msg.sender, spender, amount);\\n\\n        return true;\\n    }\\n\\n    function increaseApproval(address spender, uint256 amount) external returns (bool) {\\n        _setAllowance(msg.sender, spender, _allowance[msg.sender][spender].add(amount));\\n\\n        return true;\\n    }\\n\\n    function decreaseApproval(address spender, uint256 amount) external returns (bool) {\\n        uint256 currentAllowance = _allowance[msg.sender][spender];\\n\\n        if (amount >= currentAllowance) {\\n            _setAllowance(msg.sender, spender, 0);\\n        } else {\\n            _setAllowance(msg.sender, spender, currentAllowance.sub(amount));\\n        }\\n\\n        return true;\\n    }\\n\\n    function transfer(address recipient, uint256 amount) external override returns (bool) {\\n        _move(msg.sender, recipient, amount);\\n\\n        return true;\\n    }\\n\\n    function transferFrom(\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) external override returns (bool) {\\n        uint256 currentAllowance = _allowance[sender][msg.sender];\\n        _require(msg.sender == sender || currentAllowance >= amount, Errors.INSUFFICIENT_ALLOWANCE);\\n\\n        _move(sender, recipient, amount);\\n\\n        if (msg.sender != sender && currentAllowance != uint256(-1)) {\\n            // Because of the previous require, we know that if msg.sender != sender then currentAllowance >= amount\\n            _setAllowance(sender, msg.sender, currentAllowance - amount);\\n        }\\n\\n        return true;\\n    }\\n\\n    function permit(\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) public virtual override {\\n        // solhint-disable-next-line not-rely-on-time\\n        _require(block.timestamp <= deadline, Errors.EXPIRED_PERMIT);\\n\\n        uint256 nonce = _nonces[owner];\\n\\n        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPE_HASH, owner, spender, value, nonce, deadline));\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n\\n        address signer = ecrecover(hash, v, r, s);\\n        _require((signer != address(0)) && (signer == owner), Errors.INVALID_SIGNATURE);\\n\\n        _nonces[owner] = nonce + 1;\\n        _setAllowance(owner, spender, value);\\n    }\\n\\n    // Public functions\\n\\n    function name() public view returns (string memory) {\\n        return _name;\\n    }\\n\\n    function symbol() public view returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    function decimals() public pure returns (uint8) {\\n        return _DECIMALS;\\n    }\\n\\n    function totalSupply() public view override returns (uint256) {\\n        return _totalSupply;\\n    }\\n\\n    function nonces(address owner) external view override returns (uint256) {\\n        return _nonces[owner];\\n    }\\n\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view override returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    // Internal functions\\n\\n    function _mintPoolTokens(address recipient, uint256 amount) internal {\\n        _balance[recipient] = _balance[recipient].add(amount);\\n        _totalSupply = _totalSupply.add(amount);\\n        emit Transfer(address(0), recipient, amount);\\n    }\\n\\n    function _burnPoolTokens(address sender, uint256 amount) internal {\\n        uint256 currentBalance = _balance[sender];\\n        _require(currentBalance >= amount, Errors.INSUFFICIENT_BALANCE);\\n\\n        _balance[sender] = currentBalance - amount;\\n        _totalSupply = _totalSupply.sub(amount);\\n        emit Transfer(sender, address(0), amount);\\n    }\\n\\n    function _move(\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) internal {\\n        uint256 currentBalance = _balance[sender];\\n        _require(currentBalance >= amount, Errors.INSUFFICIENT_BALANCE);\\n        // Prohibit transfers to the zero address to avoid confusion with the\\n        // Transfer event emitted by `_burnPoolTokens`\\n        _require(recipient != address(0), Errors.ERC20_TRANSFER_TO_ZERO_ADDRESS);\\n\\n        _balance[sender] = currentBalance - amount;\\n        _balance[recipient] = _balance[recipient].add(amount);\\n\\n        emit Transfer(sender, recipient, amount);\\n    }\\n\\n    // Private functions\\n\\n    function _setAllowance(\\n        address owner,\\n        address spender,\\n        uint256 amount\\n    ) private {\\n        _allowance[owner][spender] = amount;\\n        emit Approval(owner, spender, amount);\\n    }\\n}\\n\",\"keccak256\":\"0x98ba9ab8cbd475a64405d5eecedbed1bb68b4adca54493894747f8e9f61a9e42\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/pools/BaseGeneralPool.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;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"./BasePool.sol\\\";\\nimport \\\"../vault/interfaces/IGeneralPool.sol\\\";\\n\\n/**\\n * @dev Extension of `BasePool`, adding a handler for `IGeneralPool.onSwap`.\\n *\\n * Derived contracts must implement `_onSwapGivenIn` and `_onSwapGivenOut` along with `BasePool`'s virtual functions.\\n */\\nabstract contract BaseGeneralPool is IGeneralPool, BasePool {\\n    constructor(\\n        IVault vault,\\n        string memory name,\\n        string memory symbol,\\n        IERC20[] memory tokens,\\n        uint256 swapFeePercentage,\\n        uint256 pauseWindowDuration,\\n        uint256 bufferPeriodDuration,\\n        address owner\\n    )\\n        BasePool(\\n            vault,\\n            IVault.PoolSpecialization.GENERAL,\\n            name,\\n            symbol,\\n            tokens,\\n            swapFeePercentage,\\n            pauseWindowDuration,\\n            bufferPeriodDuration,\\n            owner\\n        )\\n    {\\n        // solhint-disable-previous-line no-empty-blocks\\n    }\\n\\n    // Swap Hooks\\n\\n    function onSwap(\\n        SwapRequest memory swapRequest,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut\\n    ) external view virtual override returns (uint256) {\\n        _validateIndexes(indexIn, indexOut, _getTotalTokens());\\n        uint256[] memory scalingFactors = _scalingFactors();\\n\\n        return\\n            swapRequest.kind == IVault.SwapKind.GIVEN_IN\\n                ? _swapGivenIn(swapRequest, balances, indexIn, indexOut, scalingFactors)\\n                : _swapGivenOut(swapRequest, balances, indexIn, indexOut, scalingFactors);\\n    }\\n\\n    function _swapGivenIn(\\n        SwapRequest memory swapRequest,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut,\\n        uint256[] memory scalingFactors\\n    ) internal view returns (uint256) {\\n        // Fees are subtracted before scaling, to reduce the complexity of the rounding direction analysis.\\n        swapRequest.amount = _subtractSwapFeeAmount(swapRequest.amount);\\n\\n        _upscaleArray(balances, scalingFactors);\\n        swapRequest.amount = _upscale(swapRequest.amount, scalingFactors[indexIn]);\\n\\n        uint256 amountOut = _onSwapGivenIn(swapRequest, balances, indexIn, indexOut);\\n\\n        // amountOut tokens are exiting the Pool, so we round down.\\n        return _downscaleDown(amountOut, scalingFactors[indexOut]);\\n    }\\n\\n    function _swapGivenOut(\\n        SwapRequest memory swapRequest,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut,\\n        uint256[] memory scalingFactors\\n    ) internal view returns (uint256) {\\n        _upscaleArray(balances, scalingFactors);\\n        swapRequest.amount = _upscale(swapRequest.amount, scalingFactors[indexOut]);\\n\\n        uint256 amountIn = _onSwapGivenOut(swapRequest, balances, indexIn, indexOut);\\n\\n        // amountIn tokens are entering the Pool, so we round up.\\n        amountIn = _downscaleUp(amountIn, scalingFactors[indexIn]);\\n\\n        // Fees are added after scaling happens, to reduce the complexity of the rounding direction analysis.\\n        return _addSwapFeeAmount(amountIn);\\n    }\\n\\n    /*\\n     * @dev Called when a swap with the Pool occurs, where the amount of tokens entering the Pool is known.\\n     *\\n     * Returns the amount of tokens that will be taken from the Pool in return.\\n     *\\n     * All amounts inside `swapRequest` and `balances` are upscaled. The swap fee has already been deducted from\\n     * `swapRequest.amount`.\\n     *\\n     * The return value is also considered upscaled, and will be downscaled (rounding down) before returning it to the\\n     * Vault.\\n     */\\n    function _onSwapGivenIn(\\n        SwapRequest memory swapRequest,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut\\n    ) internal view virtual returns (uint256);\\n\\n    /*\\n     * @dev Called when a swap with the Pool occurs, where the amount of tokens exiting the Pool is known.\\n     *\\n     * Returns the amount of tokens that will be granted to the Pool in return.\\n     *\\n     * All amounts inside `swapRequest` and `balances` are upscaled.\\n     *\\n     * The return value is also considered upscaled, and will be downscaled (rounding up) before applying the swap fee\\n     * and returning it to the Vault.\\n     */\\n    function _onSwapGivenOut(\\n        SwapRequest memory swapRequest,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut\\n    ) internal view virtual returns (uint256);\\n\\n    function _validateIndexes(\\n        uint256 indexIn,\\n        uint256 indexOut,\\n        uint256 limit\\n    ) private pure {\\n        _require(indexIn < limit && indexOut < limit, Errors.OUT_OF_BOUNDS);\\n    }\\n}\\n\",\"keccak256\":\"0x5d7c075a9885e120f7bb1844efe6d20b118840f04e359ce25ea1d9f14af647a8\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/pools/BasePool.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;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../lib/math/FixedPoint.sol\\\";\\nimport \\\"../lib/helpers/InputHelpers.sol\\\";\\nimport \\\"../lib/helpers/TemporarilyPausable.sol\\\";\\nimport \\\"../lib/openzeppelin/ERC20.sol\\\";\\n\\nimport \\\"./BalancerPoolToken.sol\\\";\\nimport \\\"./BasePoolAuthorization.sol\\\";\\nimport \\\"../vault/interfaces/IVault.sol\\\";\\nimport \\\"../vault/interfaces/IBasePool.sol\\\";\\n\\n// This contract relies on tons of immutable state variables to perform efficient lookup, without resorting to storage\\n// reads. Because immutable arrays are not supported, we instead declare a fixed set of state variables plus a total\\n// count, resulting in a large number of state variables.\\n\\n// solhint-disable max-states-count\\n\\n/**\\n * @dev Reference implementation for the base layer of a Pool contract that manages a single Pool with an immutable set\\n * of registered tokens, no Asset Managers, an admin-controlled swap fee percentage, and an emergency pause mechanism.\\n *\\n * Note that neither swap fees nor the pause mechanism are used by this contract. They are passed through so that\\n * derived contracts can use them via the `_addSwapFeeAmount` and `_subtractSwapFeeAmount` functions, and the\\n * `whenNotPaused` modifier.\\n *\\n * No admin permissions are checked here: instead, this contract delegates that to the Vault's own Authorizer.\\n *\\n * Because this contract doesn't implement the swap hooks, derived contracts should generally inherit from\\n * BaseGeneralPool or BaseMinimalSwapInfoPool. Otherwise, subclasses must inherit from the corresponding interfaces\\n * and implement the swap callbacks themselves.\\n */\\nabstract contract BasePool is IBasePool, BasePoolAuthorization, BalancerPoolToken, TemporarilyPausable {\\n    using FixedPoint for uint256;\\n\\n    uint256 private constant _MIN_TOKENS = 2;\\n    uint256 private constant _MAX_TOKENS = 8;\\n\\n    // 1e18 corresponds to 1.0, or a 100% fee\\n    uint256 private constant _MIN_SWAP_FEE_PERCENTAGE = 1e12; // 0.0001%\\n    uint256 private constant _MAX_SWAP_FEE_PERCENTAGE = 1e17; // 10%\\n\\n    uint256 private constant _MINIMUM_BPT = 1e6;\\n\\n    uint256 internal _swapFeePercentage;\\n\\n    IVault private immutable _vault;\\n    bytes32 private immutable _poolId;\\n    uint256 private immutable _totalTokens;\\n\\n    IERC20 internal immutable _token0;\\n    IERC20 internal immutable _token1;\\n    IERC20 internal immutable _token2;\\n    IERC20 internal immutable _token3;\\n    IERC20 internal immutable _token4;\\n    IERC20 internal immutable _token5;\\n    IERC20 internal immutable _token6;\\n    IERC20 internal immutable _token7;\\n\\n    // All token balances are normalized to behave as if the token had 18 decimals. We assume a token's decimals will\\n    // not change throughout its lifetime, and store the corresponding scaling factor for each at construction time.\\n    // These factors are always greater than or equal to one: tokens with more than 18 decimals are not supported.\\n\\n    uint256 internal immutable _scalingFactor0;\\n    uint256 internal immutable _scalingFactor1;\\n    uint256 internal immutable _scalingFactor2;\\n    uint256 internal immutable _scalingFactor3;\\n    uint256 internal immutable _scalingFactor4;\\n    uint256 internal immutable _scalingFactor5;\\n    uint256 internal immutable _scalingFactor6;\\n    uint256 internal immutable _scalingFactor7;\\n\\n    event SwapFeeChanged(uint256 swapFeePercentage);\\n\\n    constructor(\\n        IVault vault,\\n        IVault.PoolSpecialization specialization,\\n        string memory name,\\n        string memory symbol,\\n        IERC20[] memory tokens,\\n        uint256 swapFeePercentage,\\n        uint256 pauseWindowDuration,\\n        uint256 bufferPeriodDuration,\\n        address owner\\n    )\\n        // Base Pools are expected to be deployed using factories. By using the factory address as the action\\n        // disambiguator, we make all Pools deployed by the same factory share action identifiers. This allows for\\n        // simpler management of permissions (such as being able to manage granting the 'set fee percentage' action in\\n        // any Pool created by the same factory), while still making action identifiers unique among different factories\\n        // if the selectors match, preventing accidental errors.\\n        Authentication(bytes32(uint256(msg.sender)))\\n        BalancerPoolToken(name, symbol)\\n        BasePoolAuthorization(owner)\\n        TemporarilyPausable(pauseWindowDuration, bufferPeriodDuration)\\n    {\\n        _require(tokens.length >= _MIN_TOKENS, Errors.MIN_TOKENS);\\n        _require(tokens.length <= _MAX_TOKENS, Errors.MAX_TOKENS);\\n\\n        // The Vault only requires the token list to be ordered for the Two Token Pools specialization. However,\\n        // to make the developer experience consistent, we are requiring this condition for all the native pools.\\n        // Also, since these Pools will register tokens only once, we can ensure the Pool tokens will follow the same\\n        // order. We rely on this property to make Pools simpler to write, as it lets us assume that the\\n        // order of token-specific parameters (such as token weights) will not change.\\n        InputHelpers.ensureArrayIsSorted(tokens);\\n\\n        _require(swapFeePercentage >= _MIN_SWAP_FEE_PERCENTAGE, Errors.MIN_SWAP_FEE_PERCENTAGE);\\n        _require(swapFeePercentage <= _MAX_SWAP_FEE_PERCENTAGE, Errors.MAX_SWAP_FEE_PERCENTAGE);\\n\\n        bytes32 poolId = vault.registerPool(specialization);\\n\\n        // Pass in zero addresses for Asset Managers\\n        vault.registerTokens(poolId, tokens, new address[](tokens.length));\\n\\n        // Set immutable state variables - these cannot be read from during construction\\n\\n        _vault = vault;\\n        _poolId = poolId;\\n        _swapFeePercentage = swapFeePercentage;\\n        _totalTokens = tokens.length;\\n\\n        // Immutable variables cannot be initialized inside an if statement, so we must do conditional assignments\\n\\n        _token0 = tokens.length > 0 ? tokens[0] : IERC20(0);\\n        _token1 = tokens.length > 1 ? tokens[1] : IERC20(0);\\n        _token2 = tokens.length > 2 ? tokens[2] : IERC20(0);\\n        _token3 = tokens.length > 3 ? tokens[3] : IERC20(0);\\n        _token4 = tokens.length > 4 ? tokens[4] : IERC20(0);\\n        _token5 = tokens.length > 5 ? tokens[5] : IERC20(0);\\n        _token6 = tokens.length > 6 ? tokens[6] : IERC20(0);\\n        _token7 = tokens.length > 7 ? tokens[7] : IERC20(0);\\n\\n        _scalingFactor0 = tokens.length > 0 ? _computeScalingFactor(tokens[0]) : 0;\\n        _scalingFactor1 = tokens.length > 1 ? _computeScalingFactor(tokens[1]) : 0;\\n        _scalingFactor2 = tokens.length > 2 ? _computeScalingFactor(tokens[2]) : 0;\\n        _scalingFactor3 = tokens.length > 3 ? _computeScalingFactor(tokens[3]) : 0;\\n        _scalingFactor4 = tokens.length > 4 ? _computeScalingFactor(tokens[4]) : 0;\\n        _scalingFactor5 = tokens.length > 5 ? _computeScalingFactor(tokens[5]) : 0;\\n        _scalingFactor6 = tokens.length > 6 ? _computeScalingFactor(tokens[6]) : 0;\\n        _scalingFactor7 = tokens.length > 7 ? _computeScalingFactor(tokens[7]) : 0;\\n    }\\n\\n    // Getters / Setters\\n\\n    function getVault() public view returns (IVault) {\\n        return _vault;\\n    }\\n\\n    function getPoolId() public view returns (bytes32) {\\n        return _poolId;\\n    }\\n\\n    function _getTotalTokens() internal view returns (uint256) {\\n        return _totalTokens;\\n    }\\n\\n    function getSwapFeePercentage() external view returns (uint256) {\\n        return _swapFeePercentage;\\n    }\\n\\n    // Caller must be approved by the Vault's Authorizer\\n    function setSwapFeePercentage(uint256 swapFeePercentage) external virtual authenticate whenNotPaused {\\n        _require(swapFeePercentage >= _MIN_SWAP_FEE_PERCENTAGE, Errors.MIN_SWAP_FEE_PERCENTAGE);\\n        _require(swapFeePercentage <= _MAX_SWAP_FEE_PERCENTAGE, Errors.MAX_SWAP_FEE_PERCENTAGE);\\n\\n        _swapFeePercentage = swapFeePercentage;\\n        emit SwapFeeChanged(swapFeePercentage);\\n    }\\n\\n    // Caller must be approved by the Vault's Authorizer\\n    function setPaused(bool paused) external authenticate {\\n        _setPaused(paused);\\n    }\\n\\n    // Join / Exit Hooks\\n\\n    modifier onlyVault(bytes32 poolId) {\\n        _require(msg.sender == address(getVault()), Errors.CALLER_NOT_VAULT);\\n        _require(poolId == getPoolId(), Errors.INVALID_POOL_ID);\\n        _;\\n    }\\n\\n    function onJoinPool(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    ) external virtual override onlyVault(poolId) returns (uint256[] memory, uint256[] memory) {\\n        uint256[] memory scalingFactors = _scalingFactors();\\n\\n        if (totalSupply() == 0) {\\n            (uint256 bptAmountOut, uint256[] memory amountsIn) = _onInitializePool(poolId, sender, recipient, userData);\\n\\n            // On initialization, we lock _MINIMUM_BPT by minting it for the zero address. This BPT acts as a minimum\\n            // as it will never be burned, which reduces potential issues with rounding, and also prevents the Pool from\\n            // ever being fully drained.\\n            _require(bptAmountOut >= _MINIMUM_BPT, Errors.MINIMUM_BPT);\\n            _mintPoolTokens(address(0), _MINIMUM_BPT);\\n            _mintPoolTokens(recipient, bptAmountOut - _MINIMUM_BPT);\\n\\n            // amountsIn are amounts entering the Pool, so we round up.\\n            _downscaleUpArray(amountsIn, scalingFactors);\\n\\n            return (amountsIn, new uint256[](_getTotalTokens()));\\n        } else {\\n            _upscaleArray(balances, scalingFactors);\\n            (uint256 bptAmountOut, uint256[] memory amountsIn, uint256[] memory dueProtocolFeeAmounts) = _onJoinPool(\\n                poolId,\\n                sender,\\n                recipient,\\n                balances,\\n                lastChangeBlock,\\n                protocolSwapFeePercentage,\\n                userData\\n            );\\n\\n            // Note we no longer use `balances` after calling `_onJoinPool`, which may mutate it.\\n\\n            _mintPoolTokens(recipient, bptAmountOut);\\n\\n            // amountsIn are amounts entering the Pool, so we round up.\\n            _downscaleUpArray(amountsIn, scalingFactors);\\n            // dueProtocolFeeAmounts are amounts exiting the Pool, so we round down.\\n            _downscaleDownArray(dueProtocolFeeAmounts, scalingFactors);\\n\\n            return (amountsIn, dueProtocolFeeAmounts);\\n        }\\n    }\\n\\n    function onExitPool(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    ) external virtual override onlyVault(poolId) returns (uint256[] memory, uint256[] memory) {\\n        uint256[] memory scalingFactors = _scalingFactors();\\n        _upscaleArray(balances, scalingFactors);\\n\\n        (uint256 bptAmountIn, uint256[] memory amountsOut, uint256[] memory dueProtocolFeeAmounts) = _onExitPool(\\n            poolId,\\n            sender,\\n            recipient,\\n            balances,\\n            lastChangeBlock,\\n            protocolSwapFeePercentage,\\n            userData\\n        );\\n\\n        // Note we no longer use `balances` after calling `_onExitPool`, which may mutate it.\\n\\n        _burnPoolTokens(sender, bptAmountIn);\\n\\n        // Both amountsOut and dueProtocolFeeAmounts are amounts exiting the Pool, so we round down.\\n        _downscaleDownArray(amountsOut, scalingFactors);\\n        _downscaleDownArray(dueProtocolFeeAmounts, scalingFactors);\\n\\n        return (amountsOut, dueProtocolFeeAmounts);\\n    }\\n\\n    // Query functions\\n\\n    /**\\n     * @dev Returns the amount of BPT that would be granted to `recipient` if the `onJoinPool` hook were called by the\\n     * Vault with the same arguments, along with the number of tokens `sender` would have to supply.\\n     *\\n     * This function is not meant to be called directly, but rather from a helper contract that fetches current Vault\\n     * data, such as the protocol swap fee percentage and Pool balances.\\n     *\\n     * Like `IVault.queryBatchSwap`, this function is not view due to internal implementation details: the caller must\\n     * explicitly use eth_call instead of eth_sendTransaction.\\n     */\\n    function queryJoin(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    ) external returns (uint256 bptOut, uint256[] memory amountsIn) {\\n        InputHelpers.ensureInputLengthMatch(balances.length, _getTotalTokens());\\n\\n        _queryAction(\\n            poolId,\\n            sender,\\n            recipient,\\n            balances,\\n            lastChangeBlock,\\n            protocolSwapFeePercentage,\\n            userData,\\n            _onJoinPool,\\n            _downscaleUpArray\\n        );\\n\\n        // The `return` opcode is executed directly inside `_queryAction`, so execution never reaches this statement,\\n        // and we don't need to return anything here - it just silences compiler warnings.\\n        return (bptOut, amountsIn);\\n    }\\n\\n    /**\\n     * @dev Returns the amount of BPT that would be burned from `sender` if the `onExitPool` hook were called by the\\n     * Vault with the same arguments, along with the number of tokens `recipient` would receive.\\n     *\\n     * This function is not meant to be called directly, but rather from a helper contract that fetches current Vault\\n     * data, such as the protocol swap fee percentage and Pool balances.\\n     *\\n     * Like `IVault.queryBatchSwap`, this function is not view due to internal implementation details: the caller must\\n     * explicitly use eth_call instead of eth_sendTransaction.\\n     */\\n    function queryExit(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    ) external returns (uint256 bptIn, uint256[] memory amountsOut) {\\n        InputHelpers.ensureInputLengthMatch(balances.length, _getTotalTokens());\\n\\n        _queryAction(\\n            poolId,\\n            sender,\\n            recipient,\\n            balances,\\n            lastChangeBlock,\\n            protocolSwapFeePercentage,\\n            userData,\\n            _onExitPool,\\n            _downscaleDownArray\\n        );\\n\\n        // The `return` opcode is executed directly inside `_queryAction`, so execution never reaches this statement,\\n        // and we don't need to return anything here - it just silences compiler warnings.\\n        return (bptIn, amountsOut);\\n    }\\n\\n    // Internal hooks to be overridden by derived contracts - all token amounts (except BPT) in these interfaces are\\n    // upscaled.\\n\\n    /**\\n     * @dev Called when the Pool is joined for the first time; that is, when the BPT total supply is zero.\\n     *\\n     * Returns the amount of BPT to mint, and the token amounts the Pool will receive in return.\\n     *\\n     * Minted BPT will be sent to `recipient`, except for _MINIMUM_BPT, which will be deducted from this amount and sent\\n     * to the zero address instead. This will cause that BPT to remain forever locked there, preventing total BTP from\\n     * ever dropping below that value, and ensuring `_onInitializePool` can only be called once in the entire Pool's\\n     * lifetime.\\n     *\\n     * The tokens granted to the Pool will be transferred from `sender`. These amounts are considered upscaled and will\\n     * be downscaled (rounding up) before being returned to the Vault.\\n     */\\n    function _onInitializePool(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        bytes memory userData\\n    ) internal virtual returns (uint256 bptAmountOut, uint256[] memory amountsIn);\\n\\n    /**\\n     * @dev Called whenever the Pool is joined after the first initialization join (see `_onInitializePool`).\\n     *\\n     * Returns the amount of BPT to mint, the token amounts that the Pool will receive in return, and the number of\\n     * tokens to pay in protocol swap fees.\\n     *\\n     * Implementations of this function might choose to mutate the `balances` array to save gas (e.g. when\\n     * performing intermediate calculations, such as subtraction of due protocol fees). This can be done safely.\\n     *\\n     * Minted BPT will be sent to `recipient`.\\n     *\\n     * The tokens granted to the Pool will be transferred from `sender`. These amounts are considered upscaled and will\\n     * be downscaled (rounding up) before being returned to the Vault.\\n     *\\n     * Due protocol swap fees will be taken from the Pool's balance in the Vault (see `IBasePool.onJoinPool`). These\\n     * amounts are considered upscaled and will be downscaled (rounding down) before being returned to the Vault.\\n     */\\n    function _onJoinPool(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    )\\n        internal\\n        virtual\\n        returns (\\n            uint256 bptAmountOut,\\n            uint256[] memory amountsIn,\\n            uint256[] memory dueProtocolFeeAmounts\\n        );\\n\\n    /**\\n     * @dev Called whenever the Pool is exited.\\n     *\\n     * Returns the amount of BPT to burn, the token amounts for each Pool token that the Pool will grant in return, and\\n     * the number of tokens to pay in protocol swap fees.\\n     *\\n     * Implementations of this function might choose to mutate the `balances` array to save gas (e.g. when\\n     * performing intermediate calculations, such as subtraction of due protocol fees). This can be done safely.\\n     *\\n     * BPT will be burnt from `sender`.\\n     *\\n     * The Pool will grant tokens to `recipient`. These amounts are considered upscaled and will be downscaled\\n     * (rounding down) before being returned to the Vault.\\n     *\\n     * Due protocol swap fees will be taken from the Pool's balance in the Vault (see `IBasePool.onExitPool`). These\\n     * amounts are considered upscaled and will be downscaled (rounding down) before being returned to the Vault.\\n     */\\n    function _onExitPool(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    )\\n        internal\\n        virtual\\n        returns (\\n            uint256 bptAmountIn,\\n            uint256[] memory amountsOut,\\n            uint256[] memory dueProtocolFeeAmounts\\n        );\\n\\n    // Internal functions\\n\\n    /**\\n     * @dev Adds swap fee amount to `amount`, returning a higher value.\\n     */\\n    function _addSwapFeeAmount(uint256 amount) internal view returns (uint256) {\\n        // This returns amount + fee amount, so we round up (favoring a higher fee amount).\\n        return amount.divUp(_swapFeePercentage.complement());\\n    }\\n\\n    /**\\n     * @dev Subtracts swap fee amount from `amount`, returning a lower value.\\n     */\\n    function _subtractSwapFeeAmount(uint256 amount) internal view returns (uint256) {\\n        // This returns amount - fee amount, so we round up (favoring a higher fee amount).\\n        uint256 feeAmount = amount.mulUp(_swapFeePercentage);\\n        return amount.sub(feeAmount);\\n    }\\n\\n    // Scaling\\n\\n    /**\\n     * @dev Returns a scaling factor that, when multiplied to a token amount for `token`, normalizes its balance as if\\n     * it had 18 decimals.\\n     */\\n    function _computeScalingFactor(IERC20 token) private view returns (uint256) {\\n        // Tokens that don't implement the `decimals` method are not supported.\\n        uint256 tokenDecimals = ERC20(address(token)).decimals();\\n\\n        // Tokens with more than 18 decimals are not supported.\\n        uint256 decimalsDifference = Math.sub(18, tokenDecimals);\\n        return 10**decimalsDifference;\\n    }\\n\\n    /**\\n     * @dev Returns the scaling factor for one of the Pool's tokens. Reverts if `token` is not a token registered by the\\n     * Pool.\\n     */\\n    function _scalingFactor(IERC20 token) internal view returns (uint256) {\\n        // prettier-ignore\\n        if (token == _token0) { return _scalingFactor0; }\\n        else if (token == _token1) { return _scalingFactor1; }\\n        else if (token == _token2) { return _scalingFactor2; }\\n        else if (token == _token3) { return _scalingFactor3; }\\n        else if (token == _token4) { return _scalingFactor4; }\\n        else if (token == _token5) { return _scalingFactor5; }\\n        else if (token == _token6) { return _scalingFactor6; }\\n        else if (token == _token7) { return _scalingFactor7; }\\n        else {\\n            _revert(Errors.INVALID_TOKEN);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns all the scaling factors in the same order as the registered tokens. The Vault will always\\n     * pass balances in this order when calling any of the Pool hooks\\n     */\\n    function _scalingFactors() internal view returns (uint256[] memory) {\\n        uint256 totalTokens = _getTotalTokens();\\n        uint256[] memory scalingFactors = new uint256[](totalTokens);\\n\\n        // prettier-ignore\\n        {\\n            if (totalTokens > 0) { scalingFactors[0] = _scalingFactor0; } else { return scalingFactors; }\\n            if (totalTokens > 1) { scalingFactors[1] = _scalingFactor1; } else { return scalingFactors; }\\n            if (totalTokens > 2) { scalingFactors[2] = _scalingFactor2; } else { return scalingFactors; }\\n            if (totalTokens > 3) { scalingFactors[3] = _scalingFactor3; } else { return scalingFactors; }\\n            if (totalTokens > 4) { scalingFactors[4] = _scalingFactor4; } else { return scalingFactors; }\\n            if (totalTokens > 5) { scalingFactors[5] = _scalingFactor5; } else { return scalingFactors; }\\n            if (totalTokens > 6) { scalingFactors[6] = _scalingFactor6; } else { return scalingFactors; }\\n            if (totalTokens > 7) { scalingFactors[7] = _scalingFactor7; } else { return scalingFactors; }\\n        }\\n\\n        return scalingFactors;\\n    }\\n\\n    /**\\n     * @dev Applies `scalingFactor` to `amount`, resulting in a larger or equal value depending on whether it needed\\n     * scaling or not.\\n     */\\n    function _upscale(uint256 amount, uint256 scalingFactor) internal pure returns (uint256) {\\n        return Math.mul(amount, scalingFactor);\\n    }\\n\\n    /**\\n     * @dev Same as `_upscale`, but for an entire array. This function does not return anything, but instead *mutates*\\n     * the `amounts` array.\\n     */\\n    function _upscaleArray(uint256[] memory amounts, uint256[] memory scalingFactors) internal view {\\n        for (uint256 i = 0; i < _getTotalTokens(); ++i) {\\n            amounts[i] = Math.mul(amounts[i], scalingFactors[i]);\\n        }\\n    }\\n\\n    /**\\n     * @dev Reverses the `scalingFactor` applied to `amount`, resulting in a smaller or equal value depending on\\n     * whether it needed scaling or not. The result is rounded down.\\n     */\\n    function _downscaleDown(uint256 amount, uint256 scalingFactor) internal pure returns (uint256) {\\n        return Math.divDown(amount, scalingFactor);\\n    }\\n\\n    /**\\n     * @dev Same as `_downscaleDown`, but for an entire array. This function does not return anything, but instead\\n     * *mutates* the `amounts` array.\\n     */\\n    function _downscaleDownArray(uint256[] memory amounts, uint256[] memory scalingFactors) internal view {\\n        for (uint256 i = 0; i < _getTotalTokens(); ++i) {\\n            amounts[i] = Math.divDown(amounts[i], scalingFactors[i]);\\n        }\\n    }\\n\\n    /**\\n     * @dev Reverses the `scalingFactor` applied to `amount`, resulting in a smaller or equal value depending on\\n     * whether it needed scaling or not. The result is rounded up.\\n     */\\n    function _downscaleUp(uint256 amount, uint256 scalingFactor) internal pure returns (uint256) {\\n        return Math.divUp(amount, scalingFactor);\\n    }\\n\\n    /**\\n     * @dev Same as `_downscaleUp`, but for an entire array. This function does not return anything, but instead\\n     * *mutates* the `amounts` array.\\n     */\\n    function _downscaleUpArray(uint256[] memory amounts, uint256[] memory scalingFactors) internal view {\\n        for (uint256 i = 0; i < _getTotalTokens(); ++i) {\\n            amounts[i] = Math.divUp(amounts[i], scalingFactors[i]);\\n        }\\n    }\\n\\n    function _getAuthorizer() internal view override returns (IAuthorizer) {\\n        // Access control management is delegated to the Vault's Authorizer. This lets Balancer Governance manage which\\n        // accounts can call permissioned functions: for example, to perform emergency pauses.\\n        // If the owner is delegated, then *all* permissioned functions, including `setSwapFeePercentage`, will be under\\n        // Governance control.\\n        return getVault().getAuthorizer();\\n    }\\n\\n    function _queryAction(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData,\\n        function(bytes32, address, address, uint256[] memory, uint256, uint256, bytes memory)\\n            internal\\n            returns (uint256, uint256[] memory, uint256[] memory) _action,\\n        function(uint256[] memory, uint256[] memory) internal view _downscaleArray\\n    ) private {\\n        // This uses the same technique used by the Vault in queryBatchSwap. Refer to that function for a detailed\\n        // explanation.\\n\\n        if (msg.sender != address(this)) {\\n            // We perform an external call to ourselves, forwarding the same calldata. In this call, the else clause of\\n            // the preceding if statement will be executed instead.\\n\\n            // solhint-disable-next-line avoid-low-level-calls\\n            (bool success, ) = address(this).call(msg.data);\\n\\n            // solhint-disable-next-line no-inline-assembly\\n            assembly {\\n                // This call should always revert to decode the bpt and token amounts from the revert reason\\n                switch success\\n                    case 0 {\\n                        // Note we are manually writing the memory slot 0. We can safely overwrite whatever is\\n                        // stored there as we take full control of the execution and then immediately return.\\n\\n                        // We copy the first 4 bytes to check if it matches with the expected signature, otherwise\\n                        // there was another revert reason and we should forward it.\\n                        returndatacopy(0, 0, 0x04)\\n                        let error := and(mload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)\\n\\n                        // If the first 4 bytes don't match with the expected signature, we forward the revert reason.\\n                        if eq(eq(error, 0x43adbafb00000000000000000000000000000000000000000000000000000000), 0) {\\n                            returndatacopy(0, 0, returndatasize())\\n                            revert(0, returndatasize())\\n                        }\\n\\n                        // The returndata contains the signature, followed by the raw memory representation of the\\n                        // `bptAmount` and `tokenAmounts` (array: length + data). We need to return an ABI-encoded\\n                        // representation of these.\\n                        // An ABI-encoded response will include one additional field to indicate the starting offset of\\n                        // the `tokenAmounts` array. The `bptAmount` will be laid out in the first word of the\\n                        // returndata.\\n                        //\\n                        // In returndata:\\n                        // [ signature ][ bptAmount ][ tokenAmounts length ][ tokenAmounts values ]\\n                        // [  4 bytes  ][  32 bytes ][       32 bytes      ][ (32 * length) bytes ]\\n                        //\\n                        // We now need to return (ABI-encoded values):\\n                        // [ bptAmount ][ tokeAmounts offset ][ tokenAmounts length ][ tokenAmounts values ]\\n                        // [  32 bytes ][       32 bytes     ][       32 bytes      ][ (32 * length) bytes ]\\n\\n                        // We copy 32 bytes for the `bptAmount` from returndata into memory.\\n                        // Note that we skip the first 4 bytes for the error signature\\n                        returndatacopy(0, 0x04, 32)\\n\\n                        // The offsets are 32-bytes long, so the array of `tokenAmounts` will start after\\n                        // the initial 64 bytes.\\n                        mstore(0x20, 64)\\n\\n                        // We now copy the raw memory array for the `tokenAmounts` from returndata into memory.\\n                        // Since bpt amount and offset take up 64 bytes, we start copying at address 0x40. We also\\n                        // skip the first 36 bytes from returndata, which correspond to the signature plus bpt amount.\\n                        returndatacopy(0x40, 0x24, sub(returndatasize(), 36))\\n\\n                        // We finally return the ABI-encoded uint256 and the array, which has a total length equal to\\n                        // the size of returndata, plus the 32 bytes of the offset but without the 4 bytes of the\\n                        // error signature.\\n                        return(0, add(returndatasize(), 28))\\n                    }\\n                    default {\\n                        // This call should always revert, but we fail nonetheless if that didn't happen\\n                        invalid()\\n                    }\\n            }\\n        } else {\\n            uint256[] memory scalingFactors = _scalingFactors();\\n            _upscaleArray(balances, scalingFactors);\\n\\n            (uint256 bptAmount, uint256[] memory tokenAmounts, ) = _action(\\n                poolId,\\n                sender,\\n                recipient,\\n                balances,\\n                lastChangeBlock,\\n                protocolSwapFeePercentage,\\n                userData\\n            );\\n\\n            _downscaleArray(tokenAmounts, scalingFactors);\\n\\n            // solhint-disable-next-line no-inline-assembly\\n            assembly {\\n                // We will return a raw representation of `bptAmount` and `tokenAmounts` in memory, which is composed of\\n                // a 32-byte uint256, followed by a 32-byte for the array length, and finally the 32-byte uint256 values\\n                // Because revert expects a size in bytes, we multiply the array length (stored at `tokenAmounts`) by 32\\n                let size := mul(mload(tokenAmounts), 32)\\n\\n                // We store the `bptAmount` in the previous slot to the `tokenAmounts` array. We can make sure there\\n                // will be at least one available slot due to how the memory scratch space works.\\n                // We can safely overwrite whatever is stored in this slot as we will revert immediately after that.\\n                let start := sub(tokenAmounts, 0x20)\\n                mstore(start, bptAmount)\\n\\n                // We send one extra value for the error signature \\\"QueryError(uint256,uint256[])\\\" which is 0x43adbafb\\n                // We use the previous slot to `bptAmount`.\\n                mstore(sub(start, 0x20), 0x0000000000000000000000000000000000000000000000000000000043adbafb)\\n                start := sub(start, 0x04)\\n\\n                // When copying from `tokenAmounts` into returndata, we copy the additional 68 bytes to also return\\n                // the `bptAmount`, the array 's length, and the error signature.\\n                revert(start, add(size, 68))\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x2c5f45afc279e0b638bef607738d3c5fd1ffa3e6d8c2996b6de96110938a2457\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/pools/BasePoolAuthorization.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;\\n\\nimport \\\"../lib/helpers/Authentication.sol\\\";\\nimport \\\"../vault/interfaces/IAuthorizer.sol\\\";\\n\\nimport \\\"./BasePool.sol\\\";\\n\\n/**\\n * @dev Base authorization layer implementation for Pools.\\n *\\n * The owner account can call some of the permissioned functions - access control of the rest is delegated to the\\n * Authorizer. Note that this owner is immutable: more sophisticated permission schemes, such as multiple ownership,\\n * granular roles, etc., could be built on top of this by making the owner a smart contract.\\n *\\n * Access control of all other permissioned functions is delegated to an Authorizer. It is also possible to delegate\\n * control of *all* permissioned functions to the Authorizer by setting the owner address to `_DELEGATE_OWNER`.\\n */\\nabstract contract BasePoolAuthorization is Authentication {\\n    address private immutable _owner;\\n\\n    address private constant _DELEGATE_OWNER = 0xBA1BA1ba1BA1bA1bA1Ba1BA1ba1BA1bA1ba1ba1B;\\n\\n    constructor(address owner) {\\n        _owner = owner;\\n    }\\n\\n    function getOwner() public view returns (address) {\\n        return _owner;\\n    }\\n\\n    function getAuthorizer() external view returns (IAuthorizer) {\\n        return _getAuthorizer();\\n    }\\n\\n    function _canPerform(bytes32 actionId, address account) internal view override returns (bool) {\\n        if ((getOwner() != _DELEGATE_OWNER) && _isOwnerOnlyAction(actionId)) {\\n            // Only the owner can perform \\\"owner only\\\" actions, unless the owner is delegated.\\n            return msg.sender == getOwner();\\n        } else {\\n            // Non-owner actions are always processed via the Authorizer, as \\\"owner only\\\" ones are when delegated.\\n            return _getAuthorizer().canPerform(actionId, account, address(this));\\n        }\\n    }\\n\\n    function _isOwnerOnlyAction(bytes32 actionId) private view returns (bool) {\\n        // This implementation hardcodes the setSwapFeePercentage action identifier.\\n        return actionId == getActionId(BasePool.setSwapFeePercentage.selector);\\n    }\\n\\n    function _getAuthorizer() internal view virtual returns (IAuthorizer);\\n}\\n\",\"keccak256\":\"0x080dfa64851c8f2bc9e989d37154453cf154609a792f8ca554478450290be7db\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/pools/stable/StableMath.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;\\n\\nimport \\\"../../lib/math/Math.sol\\\";\\nimport \\\"../../lib/math/FixedPoint.sol\\\";\\n\\n// This is a contract to emulate file-level functions. Convert to a library\\n// after the migration to solc v0.7.1.\\n\\n// solhint-disable private-vars-leading-underscore\\n// solhint-disable var-name-mixedcase\\n\\ncontract StableMath {\\n    using FixedPoint for uint256;\\n\\n    uint256 internal constant _MIN_AMP = 1e18;\\n    uint256 internal constant _MAX_AMP = 5000 * (1e18);\\n\\n    uint256 internal constant _MAX_STABLE_TOKENS = 5;\\n\\n    // Computes the invariant given the current balances, using the Newton-Raphson approximation.\\n    // The amplification parameter equals: A n^(n-1)\\n    function _calculateInvariant(uint256 amplificationParameter, uint256[] memory balances)\\n        internal\\n        pure\\n        returns (uint256)\\n    {\\n        /**********************************************************************************************\\n        // invariant                                                                                 //\\n        // D = invariant                                                  D^(n+1)                    //\\n        // A = amplification coefficient      A  n^n S + D = A D n^n + -----------                   //\\n        // S = sum of balances                                             n^n P                     //\\n        // P = product of balances                                                                   //\\n        // n = number of tokens                                                                      //\\n        *********x************************************************************************************/\\n\\n        // We round up the invariant.\\n\\n        uint256 sum = 0;\\n        uint256 numTokens = balances.length;\\n        for (uint256 i = 0; i < numTokens; i++) {\\n            sum = sum.add(balances[i]);\\n        }\\n        if (sum == 0) {\\n            return 0;\\n        }\\n        uint256 prevInvariant = 0;\\n        uint256 invariant = sum;\\n        uint256 ampTimesTotal = Math.mul(amplificationParameter, numTokens);\\n\\n        for (uint256 i = 0; i < 255; i++) {\\n            uint256 P_D = Math.mul(numTokens, balances[0]);\\n            for (uint256 j = 1; j < numTokens; j++) {\\n                P_D = Math.divUp(Math.mul(Math.mul(P_D, balances[j]), numTokens), invariant);\\n            }\\n            prevInvariant = invariant;\\n            invariant = Math.divUp(\\n                Math.mul(Math.mul(numTokens, invariant), invariant).add(Math.mul(Math.mul(ampTimesTotal, sum), P_D)),\\n                Math.mul(numTokens.add(1), invariant).add(Math.mul(ampTimesTotal.sub(1), P_D))\\n            );\\n\\n            if (invariant > prevInvariant) {\\n                if (invariant.sub(prevInvariant) <= 1) {\\n                    break;\\n                }\\n            } else if (prevInvariant.sub(invariant) <= 1) {\\n                break;\\n            }\\n        }\\n        return invariant;\\n    }\\n\\n    // Computes how many tokens can be taken out of a pool if `tokenAmountIn` are sent, given the current balances.\\n    // The amplification parameter equals: A n^(n-1)\\n    function _calcOutGivenIn(\\n        uint256 amplificationParameter,\\n        uint256[] memory balances,\\n        uint256 tokenIndexIn,\\n        uint256 tokenIndexOut,\\n        uint256 tokenAmountIn\\n    ) internal pure returns (uint256) {\\n        /**************************************************************************************************************\\n        // outGivenIn token x for y - polynomial equation to solve                                                   //\\n        // ay = amount out to calculate                                                                              //\\n        // by = balance token out                                                                                    //\\n        // y = by - ay (finalBalanceOut)                                                                             //\\n        // D = invariant                                               D                     D^(n+1)                 //\\n        // A = amplification coefficient               y^2 + ( S - ----------  - D) * y -  ------------- = 0         //\\n        // n = number of tokens                                    (A * n^n)               A * n^2n * P              //\\n        // S = sum of final balances but y                                                                           //\\n        // P = product of final balances but y                                                                       //\\n        **************************************************************************************************************/\\n\\n        // Amount out, so we round down overall.\\n\\n        uint256 invariant = _calculateInvariant(amplificationParameter, balances);\\n\\n        balances[tokenIndexIn] = balances[tokenIndexIn].add(tokenAmountIn);\\n\\n        uint256 finalBalanceOut = _getTokenBalanceGivenInvariantAndAllOtherBalances(\\n            amplificationParameter,\\n            balances,\\n            invariant,\\n            tokenIndexOut\\n        );\\n\\n        balances[tokenIndexIn] = balances[tokenIndexIn].sub(tokenAmountIn);\\n\\n        return balances[tokenIndexOut].sub(finalBalanceOut).sub(1);\\n    }\\n\\n    // Computes how many tokens must be sent to a pool if `tokenAmountOut` are sent given the\\n    // current balances, using the Newton-Raphson approximation.\\n    // The amplification parameter equals: A n^(n-1)\\n    function _calcInGivenOut(\\n        uint256 amplificationParameter,\\n        uint256[] memory balances,\\n        uint256 tokenIndexIn,\\n        uint256 tokenIndexOut,\\n        uint256 tokenAmountOut\\n    ) internal pure returns (uint256) {\\n        /**************************************************************************************************************\\n        // inGivenOut token x for y - polynomial equation to solve                                                   //\\n        // ax = amount in to calculate                                                                               //\\n        // bx = balance token in                                                                                     //\\n        // x = bx + ax (finalBalanceIn)                                                                              //\\n        // D = invariant                                                D                     D^(n+1)                //\\n        // A = amplification coefficient               x^2 + ( S - ----------  - D) * x -  ------------- = 0         //\\n        // n = number of tokens                                     (A * n^n)               A * n^2n * P             //\\n        // S = sum of final balances but x                                                                           //\\n        // P = product of final balances but x                                                                       //\\n        **************************************************************************************************************/\\n\\n        // Amount in, so we round up overall.\\n\\n        uint256 invariant = _calculateInvariant(amplificationParameter, balances);\\n\\n        balances[tokenIndexOut] = balances[tokenIndexOut].sub(tokenAmountOut);\\n\\n        uint256 finalBalanceIn = _getTokenBalanceGivenInvariantAndAllOtherBalances(\\n            amplificationParameter,\\n            balances,\\n            invariant,\\n            tokenIndexIn\\n        );\\n\\n        balances[tokenIndexOut] = balances[tokenIndexOut].add(tokenAmountOut);\\n\\n        return finalBalanceIn.sub(balances[tokenIndexIn]).add(1);\\n    }\\n\\n    /*\\n    TODO: document it correctly\\n    Flow of calculations:\\n    amountsTokenIn -> amountsInProportional ->\\n    amountsInPercentageExcess -> amountsInAfterFee -> newInvariant -> amountBPTOut\\n    TODO: remove equations below and save them to Notion documentation\\n    amountInPercentageExcess = 1 - amountInProportional/amountIn (if amountIn>amountInProportional)\\n    amountInAfterFee = amountIn * (1 - swapFeePercentage * amountInPercentageExcess)\\n    amountInAfterFee = amountIn - fee amount\\n    fee amount = (amountIn - amountInProportional) * swapFeePercentage\\n    amountInAfterFee = amountIn - (amountIn - amountInProportional) * swapFeePercentage\\n    amountInAfterFee = amountIn * (1 - (1 - amountInProportional/amountIn) * swapFeePercentage)\\n    amountInAfterFee = amountIn * (1 - amountInPercentageExcess * swapFeePercentage)\\n    */\\n    function _calcBptOutGivenExactTokensIn(\\n        uint256 amp,\\n        uint256[] memory balances,\\n        uint256[] memory amountsIn,\\n        uint256 bptTotalSupply,\\n        uint256 swapFeePercentage\\n    ) internal pure returns (uint256) {\\n        // BPT out, so we round down overall.\\n\\n        // Get current invariant\\n        uint256 currentInvariant = _calculateInvariant(amp, balances);\\n\\n        // First loop calculates the sum of all token balances, which will be used to calculate\\n        // the current weights of each token, relative to this sum\\n        uint256 sumBalances = 0;\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            sumBalances = sumBalances.add(balances[i]);\\n        }\\n\\n        // Calculate the weighted balance ratio without considering fees\\n        uint256[] memory tokenBalanceRatiosWithoutFee = new uint256[](amountsIn.length);\\n        // The weighted sum of token balance ratios without fee\\n        uint256 weightedBalanceRatio = 0;\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            uint256 currentWeight = balances[i].divDown(sumBalances);\\n            tokenBalanceRatiosWithoutFee[i] = balances[i].add(amountsIn[i]).divDown(balances[i]);\\n            weightedBalanceRatio = weightedBalanceRatio.add(tokenBalanceRatiosWithoutFee[i].mulDown(currentWeight));\\n        }\\n\\n        // Second loop calculates new amounts in, taking into account the fee on the percentage excess\\n        uint256[] memory newBalances = new uint256[](balances.length);\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            // Percentage of the amount supplied that will be implicitly swapped for other tokens in the pool\\n            uint256 tokenBalancePercentageExcess;\\n            // Some tokens might have amounts supplied in excess of a 'balanced' join: these are identified if\\n            // the token's balance ratio without fee is larger than the weighted balance ratio, and swap fees are\\n            // charged on the swap amount\\n            if (weightedBalanceRatio >= tokenBalanceRatiosWithoutFee[i]) {\\n                tokenBalancePercentageExcess = 0;\\n            } else {\\n                tokenBalancePercentageExcess = tokenBalanceRatiosWithoutFee[i].sub(weightedBalanceRatio).divUp(\\n                    tokenBalanceRatiosWithoutFee[i].sub(FixedPoint.ONE)\\n                );\\n            }\\n\\n            uint256 swapFeeExcess = swapFeePercentage.mulUp(tokenBalancePercentageExcess);\\n\\n            uint256 amountInAfterFee = amountsIn[i].mulDown(swapFeeExcess.complement());\\n\\n            newBalances[i] = balances[i].add(amountInAfterFee);\\n        }\\n\\n        // get the new invariant, taking swap fees into account\\n        uint256 newInvariant = _calculateInvariant(amp, newBalances);\\n\\n        // return amountBPTOut\\n        return bptTotalSupply.mulDown(newInvariant.divDown(currentInvariant).sub(FixedPoint.ONE));\\n    }\\n\\n    /*\\n    TODO: document it correctly\\n    Flow of calculations:\\n    amountBPTOut -> newInvariant -> (amountInProportional, amountInAfterFee) ->\\n    amountInPercentageExcess -> amountIn\\n    */\\n    function _calcTokenInGivenExactBptOut(\\n        uint256 amp,\\n        uint256[] memory balances,\\n        uint256 tokenIndex,\\n        uint256 bptAmountOut,\\n        uint256 bptTotalSupply,\\n        uint256 swapFeePercentage\\n    ) internal pure returns (uint256) {\\n        // Token in, so we round up overall.\\n\\n        // Get the current invariant\\n        uint256 currentInvariant = _calculateInvariant(amp, balances);\\n\\n        // Calculate new invariant\\n        uint256 newInvariant = bptTotalSupply.add(bptAmountOut).divUp(bptTotalSupply).mulUp(currentInvariant);\\n\\n        // First calculate the sum of all token balances, which will be used to calculate\\n        // the current weight of each token\\n        uint256 sumBalances = 0;\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            sumBalances = sumBalances.add(balances[i]);\\n        }\\n\\n        // get amountInAfterFee\\n        uint256 newBalanceTokenIndex = _getTokenBalanceGivenInvariantAndAllOtherBalances(\\n            amp,\\n            balances,\\n            newInvariant,\\n            tokenIndex\\n        );\\n        uint256 amountInAfterFee = newBalanceTokenIndex.sub(balances[tokenIndex]);\\n\\n        // Get tokenBalancePercentageExcess\\n        uint256 currentWeight = balances[tokenIndex].divDown(sumBalances);\\n        uint256 tokenBalancePercentageExcess = currentWeight.complement();\\n\\n        uint256 swapFeeExcess = swapFeePercentage.mulUp(tokenBalancePercentageExcess);\\n\\n        return amountInAfterFee.divUp(swapFeeExcess.complement());\\n    }\\n\\n    /*\\n    Flow of calculations:\\n    amountsTokenOut -> amountsOutProportional ->\\n    amountOutPercentageExcess -> amountOutBeforeFee -> newInvariant -> amountBPTIn\\n    */\\n    function _calcBptInGivenExactTokensOut(\\n        uint256 amp,\\n        uint256[] memory balances,\\n        uint256[] memory amountsOut,\\n        uint256 bptTotalSupply,\\n        uint256 swapFee\\n    ) internal pure returns (uint256) {\\n        // BPT in, so we round up overall.\\n\\n        // Get the current invariant\\n        uint256 currentInvariant = _calculateInvariant(amp, balances);\\n\\n        // First loop calculates the sum of all token balances, which will be used to calculate\\n        // the current weights of each token relative to this sum\\n        uint256 sumBalances = 0;\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            sumBalances = sumBalances.add(balances[i]);\\n        }\\n\\n        // Calculate the weighted balance ratio without considering fees\\n        uint256[] memory tokenBalanceRatiosWithoutFee = new uint256[](amountsOut.length);\\n        uint256 weightedBalanceRatio = 0;\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            uint256 currentWeight = balances[i].divUp(sumBalances);\\n            tokenBalanceRatiosWithoutFee[i] = balances[i].sub(amountsOut[i]).divUp(balances[i]);\\n            weightedBalanceRatio = weightedBalanceRatio.add(tokenBalanceRatiosWithoutFee[i].mulUp(currentWeight));\\n        }\\n\\n        // Second loop calculates new amounts in, taking into account the fee on the percentage excess\\n        uint256[] memory newBalances = new uint256[](balances.length);\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            uint256 tokenBalancePercentageExcess;\\n            // Compare each tokenBalanceRatioWithoutFee to the total weighted ratio (weightedBalanceRatio), and\\n            // decrease the fee by the excess amount\\n            if (weightedBalanceRatio <= tokenBalanceRatiosWithoutFee[i]) {\\n                tokenBalancePercentageExcess = 0;\\n            } else {\\n                tokenBalancePercentageExcess = weightedBalanceRatio.sub(tokenBalanceRatiosWithoutFee[i]).divUp(\\n                    tokenBalanceRatiosWithoutFee[i].complement()\\n                );\\n            }\\n\\n            uint256 swapFeeExcess = swapFee.mulUp(tokenBalancePercentageExcess);\\n\\n            uint256 amountOutBeforeFee = amountsOut[i].divUp(swapFeeExcess.complement());\\n\\n            newBalances[i] = balances[i].sub(amountOutBeforeFee);\\n        }\\n\\n        // get the new invariant, taking into account swap fees\\n        uint256 newInvariant = _calculateInvariant(amp, newBalances);\\n\\n        // return amountBPTIn\\n        return bptTotalSupply.mulUp(newInvariant.divUp(currentInvariant).complement());\\n    }\\n\\n    /*\\n    TODO: document it correctly\\n    Flow of calculations:\\n    amountBPTin -> newInvariant -> (amountOutProportional, amountOutBeforeFee) ->\\n    amountOutPercentageExcess -> amountOut\\n    */\\n    function _calcTokenOutGivenExactBptIn(\\n        uint256 amp,\\n        uint256[] memory balances,\\n        uint256 tokenIndex,\\n        uint256 bptAmountIn,\\n        uint256 bptTotalSupply,\\n        uint256 swapFeePercentage\\n    ) internal pure returns (uint256) {\\n        // Get the current invariant\\n        uint256 currentInvariant = _calculateInvariant(amp, balances);\\n        // Calculate the new invariant\\n        uint256 newInvariant = bptTotalSupply.sub(bptAmountIn).divUp(bptTotalSupply).mulUp(currentInvariant);\\n\\n        // First calculate the sum of all token balances, which will be used to calculate\\n        // the current weight of each token\\n        uint256 sumBalances = 0;\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            sumBalances = sumBalances.add(balances[i]);\\n        }\\n\\n        // get amountOutBeforeFee\\n        uint256 newBalanceTokenIndex = _getTokenBalanceGivenInvariantAndAllOtherBalances(\\n            amp,\\n            balances,\\n            newInvariant,\\n            tokenIndex\\n        );\\n        uint256 amountOutBeforeFee = balances[tokenIndex].sub(newBalanceTokenIndex);\\n\\n        // Calculate tokenBalancePercentageExcess\\n        uint256 currentWeight = balances[tokenIndex].divDown(sumBalances);\\n        uint256 tokenBalancePercentageExcess = currentWeight.complement();\\n\\n        uint256 swapFeeExcess = swapFeePercentage.mulUp(tokenBalancePercentageExcess);\\n\\n        return amountOutBeforeFee.mulDown(swapFeeExcess.complement());\\n    }\\n\\n    function _calcTokensOutGivenExactBptIn(\\n        uint256[] memory balances,\\n        uint256 bptAmountIn,\\n        uint256 bptTotalSupply\\n    ) internal pure returns (uint256[] memory) {\\n        /**********************************************************************************************\\n        // exactBPTInForTokensOut                                                                    //\\n        // (per token)                                                                               //\\n        // aO = tokenAmountOut             /        bptIn         \\\\                                  //\\n        // b = tokenBalance      a0 = b * | ---------------------  |                                 //\\n        // bptIn = bptAmountIn             \\\\     bptTotalSupply    /                                 //\\n        // bpt = bptTotalSupply                                                                      //\\n        **********************************************************************************************/\\n\\n        // Since we're computing an amount out, we round down overall. This means rounding down on both the\\n        // multiplication and division.\\n\\n        uint256 bptRatio = bptAmountIn.divDown(bptTotalSupply);\\n\\n        uint256[] memory amountsOut = new uint256[](balances.length);\\n        for (uint256 i = 0; i < balances.length; i++) {\\n            amountsOut[i] = balances[i].mulDown(bptRatio);\\n        }\\n\\n        return amountsOut;\\n    }\\n\\n    // The amplification parameter equals: A n^(n-1)\\n    function _calcDueTokenProtocolSwapFeeAmount(\\n        uint256 amplificationParameter,\\n        uint256[] memory balances,\\n        uint256 lastInvariant,\\n        uint256 tokenIndex,\\n        uint256 protocolSwapFeePercentage\\n    ) internal pure returns (uint256) {\\n        /**************************************************************************************************************\\n        // oneTokenSwapFee - polynomial equation to solve                                                            //\\n        // af = fee amount to calculate in one token                                                                 //\\n        // bf = balance of fee token                                                                                 //\\n        // f = bf - af (finalBalanceFeeToken)                                                                        //\\n        // D = old invariant                                            D                     D^(n+1)                //\\n        // A = amplification coefficient               f^2 + ( S - ----------  - D) * f -  ------------- = 0         //\\n        // n = number of tokens                                    (A * n^n)               A * n^2n * P              //\\n        // S = sum of final balances but f                                                                           //\\n        // P = product of final balances but f                                                                       //\\n        **************************************************************************************************************/\\n\\n        // Protocol swap fee amount, so we round down overall.\\n\\n        uint256 finalBalanceFeeToken = _getTokenBalanceGivenInvariantAndAllOtherBalances(\\n            amplificationParameter,\\n            balances,\\n            lastInvariant,\\n            tokenIndex\\n        );\\n\\n        // Result is rounded down\\n        uint256 accumulatedTokenSwapFees = balances[tokenIndex] > finalBalanceFeeToken\\n            ? balances[tokenIndex].sub(finalBalanceFeeToken)\\n            : 0;\\n        return accumulatedTokenSwapFees.mulDown(protocolSwapFeePercentage).divDown(FixedPoint.ONE);\\n    }\\n\\n    // Private functions\\n\\n    // This function calculates the balance of a given token (tokenIndex)\\n    // given all the other balances and the invariant\\n    function _getTokenBalanceGivenInvariantAndAllOtherBalances(\\n        uint256 amplificationParameter,\\n        uint256[] memory balances,\\n        uint256 invariant,\\n        uint256 tokenIndex\\n    ) private pure returns (uint256) {\\n        // Rounds result up overall\\n\\n        uint256 ampTimesTotal = Math.mul(amplificationParameter, balances.length);\\n        uint256 sum = balances[0];\\n        uint256 P_D = Math.mul(balances.length, balances[0]);\\n        for (uint256 j = 1; j < balances.length; j++) {\\n            P_D = Math.divDown(Math.mul(Math.mul(P_D, balances[j]), balances.length), invariant);\\n            sum = sum.add(balances[j]);\\n        }\\n        sum = sum.sub(balances[tokenIndex]);\\n\\n        uint256 c = Math.divUp(Math.mul(invariant, invariant), ampTimesTotal);\\n        // We remove the balance fromm c by multiplying it\\n        c = c.mulUp(balances[tokenIndex]).divUp(P_D);\\n\\n        uint256 b = sum.add(invariant.divDown(ampTimesTotal));\\n\\n        // We iterate to find the balance\\n        uint256 prevTokenBalance = 0;\\n        // We multiply the first iteration outside the loop with the invariant to set the value of the\\n        // initial approximation.\\n        uint256 tokenBalance = invariant.mulUp(invariant).add(c).divUp(invariant.add(b));\\n\\n        for (uint256 i = 0; i < 255; i++) {\\n            prevTokenBalance = tokenBalance;\\n\\n            tokenBalance = tokenBalance.mulUp(tokenBalance).add(c).divUp(\\n                Math.mul(tokenBalance, 2).add(b).sub(invariant)\\n            );\\n\\n            if (tokenBalance > prevTokenBalance) {\\n                if (tokenBalance.sub(prevTokenBalance) <= 1) {\\n                    break;\\n                }\\n            } else if (prevTokenBalance.sub(tokenBalance) <= 1) {\\n                break;\\n            }\\n        }\\n        return tokenBalance;\\n    }\\n}\\n\",\"keccak256\":\"0x74dc5f28798be90708c30ce59d65de8a99128e642c1ed554248807ac3aaecae8\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/pools/stable/StablePool.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;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../../lib/math/FixedPoint.sol\\\";\\nimport \\\"../../lib/helpers/InputHelpers.sol\\\";\\n\\nimport \\\"../BaseGeneralPool.sol\\\";\\n\\nimport \\\"./StableMath.sol\\\";\\nimport \\\"./StablePoolUserDataHelpers.sol\\\";\\n\\ncontract StablePool is BaseGeneralPool, StableMath {\\n    using FixedPoint for uint256;\\n    using StablePoolUserDataHelpers for bytes;\\n\\n    uint256 private immutable _amplificationParameter;\\n\\n    uint256 private _lastInvariant;\\n\\n    enum JoinKind { INIT, EXACT_TOKENS_IN_FOR_BPT_OUT, TOKEN_IN_FOR_EXACT_BPT_OUT }\\n    enum ExitKind { EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, EXACT_BPT_IN_FOR_TOKENS_OUT, BPT_IN_FOR_EXACT_TOKENS_OUT }\\n\\n    constructor(\\n        IVault vault,\\n        string memory name,\\n        string memory symbol,\\n        IERC20[] memory tokens,\\n        uint256 amplificationParameter,\\n        uint256 swapFeePercentage,\\n        uint256 pauseWindowDuration,\\n        uint256 bufferPeriodDuration,\\n        address owner\\n    )\\n        BaseGeneralPool(\\n            vault,\\n            name,\\n            symbol,\\n            tokens,\\n            swapFeePercentage,\\n            pauseWindowDuration,\\n            bufferPeriodDuration,\\n            owner\\n        )\\n    {\\n        _require(amplificationParameter >= _MIN_AMP, Errors.MIN_AMP);\\n        _require(amplificationParameter <= _MAX_AMP, Errors.MAX_AMP);\\n\\n        _require(tokens.length <= _MAX_STABLE_TOKENS, Errors.MAX_STABLE_TOKENS);\\n\\n        _amplificationParameter = amplificationParameter;\\n    }\\n\\n    function getAmplificationParameter() external view returns (uint256) {\\n        return _amplificationParameter;\\n    }\\n\\n    // Base Pool handlers\\n\\n    // Swap\\n\\n    function _onSwapGivenIn(\\n        SwapRequest memory swapRequest,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut\\n    ) internal view virtual override whenNotPaused returns (uint256) {\\n        uint256 amountOut = StableMath._calcOutGivenIn(\\n            _amplificationParameter,\\n            balances,\\n            indexIn,\\n            indexOut,\\n            swapRequest.amount\\n        );\\n\\n        return amountOut;\\n    }\\n\\n    function _onSwapGivenOut(\\n        SwapRequest memory swapRequest,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut\\n    ) internal view virtual override whenNotPaused returns (uint256) {\\n        uint256 amountIn = StableMath._calcInGivenOut(\\n            _amplificationParameter,\\n            balances,\\n            indexIn,\\n            indexOut,\\n            swapRequest.amount\\n        );\\n\\n        return amountIn;\\n    }\\n\\n    // Initialize\\n\\n    function _onInitializePool(\\n        bytes32,\\n        address,\\n        address,\\n        bytes memory userData\\n    ) internal virtual override whenNotPaused returns (uint256, uint256[] memory) {\\n        StablePool.JoinKind kind = userData.joinKind();\\n        _require(kind == StablePool.JoinKind.INIT, Errors.UNINITIALIZED);\\n\\n        uint256[] memory amountsIn = userData.initialAmountsIn();\\n        InputHelpers.ensureInputLengthMatch(amountsIn.length, _getTotalTokens());\\n        _upscaleArray(amountsIn, _scalingFactors());\\n\\n        uint256 invariantAfterJoin = StableMath._calculateInvariant(_amplificationParameter, amountsIn);\\n        uint256 bptAmountOut = invariantAfterJoin;\\n\\n        _lastInvariant = invariantAfterJoin;\\n\\n        return (bptAmountOut, amountsIn);\\n    }\\n\\n    // Join\\n\\n    function _onJoinPool(\\n        bytes32,\\n        address,\\n        address,\\n        uint256[] memory balances,\\n        uint256,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    )\\n        internal\\n        virtual\\n        override\\n        whenNotPaused\\n        returns (\\n            uint256,\\n            uint256[] memory,\\n            uint256[] memory\\n        )\\n    {\\n        // Due protocol swap fee amounts are computed by measuring the growth of the invariant between the previous join\\n        // or exit event and now - the invariant's growth is due exclusively to swap fees. This avoids spending gas to\\n        // calculate the fee amounts during each individual swap.\\n        uint256[] memory dueProtocolFeeAmounts = _getDueProtocolFeeAmounts(\\n            balances,\\n            _lastInvariant,\\n            protocolSwapFeePercentage\\n        );\\n\\n        // Update the balances by subtracting the protocol fee amounts that will be charged by the Vault once this\\n        // function returns.\\n        for (uint256 i = 0; i < _getTotalTokens(); ++i) {\\n            balances[i] = balances[i].sub(dueProtocolFeeAmounts[i]);\\n        }\\n\\n        (uint256 bptAmountOut, uint256[] memory amountsIn) = _doJoin(balances, userData);\\n\\n        // Update the invariant with the balances the Pool will have after the join, in order to compute the\\n        // protocol swap fee amounts due in future joins and exits.\\n        _lastInvariant = _invariantAfterJoin(balances, amountsIn);\\n\\n        return (bptAmountOut, amountsIn, dueProtocolFeeAmounts);\\n    }\\n\\n    function _doJoin(uint256[] memory balances, bytes memory userData)\\n        private\\n        view\\n        returns (uint256, uint256[] memory)\\n    {\\n        JoinKind kind = userData.joinKind();\\n\\n        if (kind == JoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT) {\\n            return _joinExactTokensInForBPTOut(balances, userData);\\n        } else if (kind == JoinKind.TOKEN_IN_FOR_EXACT_BPT_OUT) {\\n            return _joinTokenInForExactBPTOut(balances, userData);\\n        } else {\\n            _revert(Errors.UNHANDLED_JOIN_KIND);\\n        }\\n    }\\n\\n    function _joinExactTokensInForBPTOut(uint256[] memory balances, bytes memory userData)\\n        private\\n        view\\n        returns (uint256, uint256[] memory)\\n    {\\n        (uint256[] memory amountsIn, uint256 minBPTAmountOut) = userData.exactTokensInForBptOut();\\n        InputHelpers.ensureInputLengthMatch(_getTotalTokens(), amountsIn.length);\\n        _upscaleArray(amountsIn, _scalingFactors());\\n\\n        uint256 bptAmountOut = StableMath._calcBptOutGivenExactTokensIn(\\n            _amplificationParameter,\\n            balances,\\n            amountsIn,\\n            totalSupply(),\\n            _swapFeePercentage\\n        );\\n\\n        _require(bptAmountOut >= minBPTAmountOut, Errors.BPT_OUT_MIN_AMOUNT);\\n\\n        return (bptAmountOut, amountsIn);\\n    }\\n\\n    function _joinTokenInForExactBPTOut(uint256[] memory balances, bytes memory userData)\\n        private\\n        view\\n        returns (uint256, uint256[] memory)\\n    {\\n        (uint256 bptAmountOut, uint256 tokenIndex) = userData.tokenInForExactBptOut();\\n\\n        uint256 amountIn = StableMath._calcTokenInGivenExactBptOut(\\n            _amplificationParameter,\\n            balances,\\n            tokenIndex,\\n            bptAmountOut,\\n            totalSupply(),\\n            _swapFeePercentage\\n        );\\n\\n        // We are joining with a single token, so initialize downscaledAmountsIn with zeros, and\\n        // only set downscaledAmountsIn[tokenIndex]\\n        uint256[] memory downscaledAmountsIn = new uint256[](_getTotalTokens());\\n        downscaledAmountsIn[tokenIndex] = amountIn;\\n\\n        return (bptAmountOut, downscaledAmountsIn);\\n    }\\n\\n    // Exit\\n\\n    function _onExitPool(\\n        bytes32,\\n        address,\\n        address,\\n        uint256[] memory balances,\\n        uint256,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    )\\n        internal\\n        virtual\\n        override\\n        returns (\\n            uint256 bptAmountIn,\\n            uint256[] memory amountsOut,\\n            uint256[] memory dueProtocolFeeAmounts\\n        )\\n    {\\n        if (_isNotPaused()) {\\n            // Due protocol swap fee amounts are computed by measuring the growth of the invariant between the previous\\n            // join or exit event and now - the invariant's growth is due exclusively to swap fees. This avoids\\n            // spending gas calculating fee amounts during each individual swap\\n            dueProtocolFeeAmounts = _getDueProtocolFeeAmounts(balances, _lastInvariant, protocolSwapFeePercentage);\\n\\n            // Update the balances by subtracting the protocol fee amounts that will be charged by the Vault once this\\n            // function returns.\\n            for (uint256 i = 0; i < _getTotalTokens(); ++i) {\\n                balances[i] = balances[i].sub(dueProtocolFeeAmounts[i]);\\n            }\\n        } else {\\n            // To avoid extra calculations, swap protocol fee amounts are not charged when the contract is paused.\\n            dueProtocolFeeAmounts = new uint256[](_getTotalTokens());\\n        }\\n\\n        (bptAmountIn, amountsOut) = _doExit(balances, userData);\\n\\n        // Update the invariant with the balances the Pool will have after the exit, in order to compute the\\n        // protocol swap fee amounts due in future joins and exits.\\n        _lastInvariant = _invariantAfterExit(balances, amountsOut);\\n\\n        return (bptAmountIn, amountsOut, dueProtocolFeeAmounts);\\n    }\\n\\n    function _doExit(uint256[] memory balances, bytes memory userData)\\n        private\\n        view\\n        returns (uint256, uint256[] memory)\\n    {\\n        ExitKind kind = userData.exitKind();\\n\\n        if (kind == ExitKind.EXACT_BPT_IN_FOR_ONE_TOKEN_OUT) {\\n            return _exitExactBPTInForTokenOut(balances, userData);\\n        } else if (kind == ExitKind.EXACT_BPT_IN_FOR_TOKENS_OUT) {\\n            return _exitExactBPTInForTokensOut(balances, userData);\\n        } else {\\n            // ExitKind.BPT_IN_FOR_EXACT_TOKENS_OUT\\n            return _exitBPTInForExactTokensOut(balances, userData);\\n        }\\n    }\\n\\n    function _exitExactBPTInForTokenOut(uint256[] memory balances, bytes memory userData)\\n        private\\n        view\\n        whenNotPaused\\n        returns (uint256, uint256[] memory)\\n    {\\n        // This exit function is disabled if the contract is paused.\\n        uint256 totalTokens = _getTotalTokens();\\n        (uint256 bptAmountIn, uint256 tokenIndex) = userData.exactBptInForTokenOut();\\n        _require(tokenIndex < totalTokens, Errors.OUT_OF_BOUNDS);\\n\\n        // We exit in a single token, so initialize amountsOut with zeros and only set amountsOut[tokenIndex]\\n        uint256[] memory amountsOut = new uint256[](totalTokens);\\n\\n        amountsOut[tokenIndex] = StableMath._calcTokenOutGivenExactBptIn(\\n            _amplificationParameter,\\n            balances,\\n            tokenIndex,\\n            bptAmountIn,\\n            totalSupply(),\\n            _swapFeePercentage\\n        );\\n\\n        return (bptAmountIn, amountsOut);\\n    }\\n\\n    function _exitExactBPTInForTokensOut(uint256[] memory balances, bytes memory userData)\\n        private\\n        view\\n        returns (uint256, uint256[] memory)\\n    {\\n        // This exit function is the only one that is not disabled if the contract is paused: it remains unrestricted\\n        // in an attempt to provide users with a mechanism to retrieve their tokens in case of an emergency.\\n        // This particular exit function is the only one that remains available because it is the simplest one, and\\n        // therefore the one with the lowest likelihood of errors.\\n        uint256 bptAmountIn = userData.exactBptInForTokensOut();\\n\\n        uint256[] memory amountsOut = StableMath._calcTokensOutGivenExactBptIn(balances, bptAmountIn, totalSupply());\\n\\n        return (bptAmountIn, amountsOut);\\n    }\\n\\n    function _exitBPTInForExactTokensOut(uint256[] memory balances, bytes memory userData)\\n        private\\n        view\\n        whenNotPaused\\n        returns (uint256, uint256[] memory)\\n    {\\n        // This exit function is disabled if the contract is paused.\\n\\n        (uint256[] memory amountsOut, uint256 maxBPTAmountIn) = userData.bptInForExactTokensOut();\\n        InputHelpers.ensureInputLengthMatch(amountsOut.length, _getTotalTokens());\\n\\n        _upscaleArray(amountsOut, _scalingFactors());\\n\\n        uint256 bptAmountIn = StableMath._calcBptInGivenExactTokensOut(\\n            _amplificationParameter,\\n            balances,\\n            amountsOut,\\n            totalSupply(),\\n            _swapFeePercentage\\n        );\\n\\n        _require(bptAmountIn <= maxBPTAmountIn, Errors.BPT_IN_MAX_AMOUNT);\\n\\n        return (bptAmountIn, amountsOut);\\n    }\\n\\n    // Helpers\\n\\n    function _getDueProtocolFeeAmounts(\\n        uint256[] memory balances,\\n        uint256 previousInvariant,\\n        uint256 protocolSwapFeePercentage\\n    ) private view returns (uint256[] memory) {\\n        // Initialize with zeros\\n        uint256[] memory dueProtocolFeeAmounts = new uint256[](_getTotalTokens());\\n\\n        // Early exit if there is no protocol swap fee\\n        if (protocolSwapFeePercentage == 0) {\\n            return dueProtocolFeeAmounts;\\n        }\\n\\n        // Instead of paying the protocol swap fee in all tokens proportionally, we will pay it in a single one. This\\n        // will reduce gas costs for single asset joins and exits, as at most only two Pool balances will change (the\\n        // token joined/exited, and the token in which fees will be paid).\\n\\n        // The protocol fee is charged using the token with the highest balance in the pool.\\n        uint256 chosenTokenIndex = 0;\\n        uint256 maxBalance = balances[0];\\n        for (uint256 i = 1; i < _getTotalTokens(); ++i) {\\n            uint256 currentBalance = balances[i];\\n            if (currentBalance > maxBalance) {\\n                chosenTokenIndex = i;\\n                maxBalance = currentBalance;\\n            }\\n        }\\n\\n        // Set the fee amount to pay in the selected token\\n        dueProtocolFeeAmounts[chosenTokenIndex] = StableMath._calcDueTokenProtocolSwapFeeAmount(\\n            _amplificationParameter,\\n            balances,\\n            previousInvariant,\\n            chosenTokenIndex,\\n            protocolSwapFeePercentage\\n        );\\n\\n        return dueProtocolFeeAmounts;\\n    }\\n\\n    function _invariantAfterJoin(uint256[] memory balances, uint256[] memory amountsIn) private view returns (uint256) {\\n        for (uint256 i = 0; i < _getTotalTokens(); ++i) {\\n            balances[i] = balances[i].add(amountsIn[i]);\\n        }\\n\\n        return StableMath._calculateInvariant(_amplificationParameter, balances);\\n    }\\n\\n    function _invariantAfterExit(uint256[] memory balances, uint256[] memory amountsOut)\\n        private\\n        view\\n        returns (uint256)\\n    {\\n        for (uint256 i = 0; i < _getTotalTokens(); ++i) {\\n            balances[i] = balances[i].sub(amountsOut[i]);\\n        }\\n\\n        return StableMath._calculateInvariant(_amplificationParameter, balances);\\n    }\\n\\n    /**\\n     * @dev This function returns the appreciation of one BPT relative to the\\n     * underlying tokens. This starts at 1 when the pool is created and grows over time\\n     */\\n    function getRate() public view returns (uint256) {\\n        (, uint256[] memory balances, ) = getVault().getPoolTokens(getPoolId());\\n        return StableMath._calculateInvariant(_amplificationParameter, balances).divDown(totalSupply());\\n    }\\n}\\n\",\"keccak256\":\"0x30dc67f7ae8053481e9a8ee13c1caef632eb88667393374ce961e4ba870055db\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/pools/stable/StablePoolUserDataHelpers.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;\\n\\nimport \\\"../../lib/openzeppelin/IERC20.sol\\\";\\n\\nimport \\\"./StablePool.sol\\\";\\n\\nlibrary StablePoolUserDataHelpers {\\n    function joinKind(bytes memory self) internal pure returns (StablePool.JoinKind) {\\n        return abi.decode(self, (StablePool.JoinKind));\\n    }\\n\\n    function exitKind(bytes memory self) internal pure returns (StablePool.ExitKind) {\\n        return abi.decode(self, (StablePool.ExitKind));\\n    }\\n\\n    function initialAmountsIn(bytes memory self) internal pure returns (uint256[] memory amountsIn) {\\n        (, amountsIn) = abi.decode(self, (StablePool.JoinKind, uint256[]));\\n    }\\n\\n    function exactTokensInForBptOut(bytes memory self)\\n        internal\\n        pure\\n        returns (uint256[] memory amountsIn, uint256 minBPTAmountIn)\\n    {\\n        (, amountsIn, minBPTAmountIn) = abi.decode(self, (StablePool.JoinKind, uint256[], uint256));\\n    }\\n\\n    function tokenInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut, uint256 tokenIndex) {\\n        (, bptAmountOut, tokenIndex) = abi.decode(self, (StablePool.JoinKind, uint256, uint256));\\n    }\\n\\n    function exactBptInForTokenOut(bytes memory self) internal pure returns (uint256 bptAmountIn, uint256 tokenIndex) {\\n        (, bptAmountIn, tokenIndex) = abi.decode(self, (StablePool.ExitKind, uint256, uint256));\\n    }\\n\\n    function exactBptInForTokensOut(bytes memory self) internal pure returns (uint256 bptAmountIn) {\\n        (, bptAmountIn) = abi.decode(self, (StablePool.ExitKind, uint256));\\n    }\\n\\n    function bptInForExactTokensOut(bytes memory self)\\n        internal\\n        pure\\n        returns (uint256[] memory amountsOut, uint256 maxBPTAmountIn)\\n    {\\n        (, amountsOut, maxBPTAmountIn) = abi.decode(self, (StablePool.ExitKind, uint256[], uint256));\\n    }\\n}\\n\",\"keccak256\":\"0xc098d1ec4fc41f10ec46a12dbf0bd5e1ffca9cafcbf4f8fa3b3815fd837d4f8d\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/ProtocolFeesCollector.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;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../lib/openzeppelin/IERC20.sol\\\";\\nimport \\\"../lib/helpers/InputHelpers.sol\\\";\\nimport \\\"../lib/helpers/Authentication.sol\\\";\\nimport \\\"../lib/openzeppelin/ReentrancyGuard.sol\\\";\\nimport \\\"../lib/openzeppelin/SafeERC20.sol\\\";\\n\\nimport \\\"./interfaces/IVault.sol\\\";\\nimport \\\"./interfaces/IAuthorizer.sol\\\";\\n\\n/**\\n * @dev This an auxiliary contract to the Vault, deployed by it during construction. It offloads some of the tasks the\\n * Vault performs to reduce its overall bytecode size.\\n *\\n * The current values for all protocol fee percentages are stored here, and any tokens charged as protocol fees are\\n * sent to this contract, where they may be withdrawn by authorized entities. All authorization tasks are delegated\\n * to the Vault's own authorizer.\\n */\\ncontract ProtocolFeesCollector is Authentication, ReentrancyGuard {\\n    using SafeERC20 for IERC20;\\n\\n    // Absolute maximum fee percentages (1e18 = 100%, 1e16 = 1%).\\n    uint256 private constant _MAX_PROTOCOL_SWAP_FEE_PERCENTAGE = 50e16; // 50%\\n    uint256 private constant _MAX_PROTOCOL_FLASH_LOAN_FEE_PERCENTAGE = 1e16; // 1%\\n\\n    IVault public immutable vault;\\n\\n    // All fee percentages are 18-decimal fixed point numbers.\\n\\n    // The swap fee is charged whenever a swap occurs, as a percentage of the fee charged by the Pool. These are not\\n    // actually charged on each individual swap: the `Vault` relies on the Pools being honest and reporting fees due\\n    // when users join and exit them.\\n    uint256 private _swapFeePercentage;\\n\\n    // The flash loan fee is charged whenever a flash loan occurs, as a percentage of the tokens lent.\\n    uint256 private _flashLoanFeePercentage;\\n\\n    event SwapFeePercentageChanged(uint256 newSwapFeePercentage);\\n    event FlashLoanFeePercentageChanged(uint256 newFlashLoanFeePercentage);\\n\\n    constructor(IVault _vault)\\n        // The ProtocolFeesCollector is a singleton, so it simply uses its own address to disambiguate action\\n        // identifiers.\\n        Authentication(bytes32(uint256(address(this))))\\n    {\\n        vault = _vault;\\n    }\\n\\n    function withdrawCollectedFees(\\n        IERC20[] calldata tokens,\\n        uint256[] calldata amounts,\\n        address recipient\\n    ) external nonReentrant authenticate {\\n        InputHelpers.ensureInputLengthMatch(tokens.length, amounts.length);\\n\\n        for (uint256 i = 0; i < tokens.length; ++i) {\\n            IERC20 token = tokens[i];\\n            uint256 amount = amounts[i];\\n            token.safeTransfer(recipient, amount);\\n        }\\n    }\\n\\n    function setSwapFeePercentage(uint256 newSwapFeePercentage) external authenticate {\\n        _require(newSwapFeePercentage <= _MAX_PROTOCOL_SWAP_FEE_PERCENTAGE, Errors.SWAP_FEE_PERCENTAGE_TOO_HIGH);\\n        _swapFeePercentage = newSwapFeePercentage;\\n        emit SwapFeePercentageChanged(newSwapFeePercentage);\\n    }\\n\\n    function setFlashLoanFeePercentage(uint256 newFlashLoanFeePercentage) external authenticate {\\n        _require(\\n            newFlashLoanFeePercentage <= _MAX_PROTOCOL_FLASH_LOAN_FEE_PERCENTAGE,\\n            Errors.FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH\\n        );\\n        _flashLoanFeePercentage = newFlashLoanFeePercentage;\\n        emit FlashLoanFeePercentageChanged(newFlashLoanFeePercentage);\\n    }\\n\\n    function getSwapFeePercentage() external view returns (uint256) {\\n        return _swapFeePercentage;\\n    }\\n\\n    function getFlashLoanFeePercentage() external view returns (uint256) {\\n        return _flashLoanFeePercentage;\\n    }\\n\\n    function getCollectedFeeAmounts(IERC20[] memory tokens) external view returns (uint256[] memory feeAmounts) {\\n        feeAmounts = new uint256[](tokens.length);\\n        for (uint256 i = 0; i < tokens.length; ++i) {\\n            feeAmounts[i] = tokens[i].balanceOf(address(this));\\n        }\\n    }\\n\\n    function getAuthorizer() external view returns (IAuthorizer) {\\n        return _getAuthorizer();\\n    }\\n\\n    function _canPerform(bytes32 actionId, address account) internal view override returns (bool) {\\n        return _getAuthorizer().canPerform(actionId, account, address(this));\\n    }\\n\\n    function _getAuthorizer() internal view returns (IAuthorizer) {\\n        return vault.getAuthorizer();\\n    }\\n}\\n\",\"keccak256\":\"0x67a0898b29a356085f4d7a83c52d1c794ebf07b6522133c9b9c7f5faf10d2184\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/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;\\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\",\"keccak256\":\"0x70ecf1d48c285d78718bd2e159345677038ed8a81c74444bedd6a5c61af9aff6\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/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;\\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\",\"keccak256\":\"0x792871e208bba1dad291f8d1cffad86f4afa5e2360816bd9c43481f7297155f5\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/IBasePool.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;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"./IVault.sol\\\";\\nimport \\\"./IPoolSwapStructs.sol\\\";\\n\\n/**\\n * @dev Interface for adding and removing liquidity that all Pool contracts should implement. Note that this is not\\n * the complete Pool contract interface, as it is missing the swap hooks. Pool contracts should also inherit from\\n * either IGeneralPool or IMinimalSwapInfoPool\\n */\\ninterface IBasePool is IPoolSwapStructs {\\n    /**\\n     * @dev Called by the Vault when a user calls `IVault.joinPool` to add liquidity to this Pool. Returns how many of\\n     * each registered token the user should provide, as well as the amount of protocol fees the Pool owes to the Vault.\\n     * The Vault will then take tokens from `sender` and add them to the Pool's balances, as well as collect\\n     * the reported amount in protocol fees, which the pool should calculate based on `protocolSwapFeePercentage`.\\n     *\\n     * Protocol fees are reported and charged on join events so that the Pool is free of debt whenever new users join.\\n     *\\n     * `sender` is the account performing the join (from which tokens will be withdrawn), and `recipient` is the account\\n     * designated to receive any benefits (typically pool shares). `currentBalances` contains the total balances\\n     * for each token the Pool registered in the Vault, in the same order that `IVault.getPoolTokens` would return.\\n     *\\n     * `lastChangeBlock` is the last block in which *any* of the Pool's registered tokens last changed its total\\n     * balance.\\n     *\\n     * `userData` contains any pool-specific instructions needed to perform the calculations, such as the type of\\n     * join (e.g., proportional given an amount of pool shares, single-asset, multi-asset, etc.)\\n     *\\n     * Contracts implementing this function should check that the caller is indeed the Vault before performing any\\n     * state-changing operations, such as minting pool shares.\\n     */\\n    function onJoinPool(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    ) external returns (uint256[] memory amountsIn, uint256[] memory dueProtocolFeeAmounts);\\n\\n    /**\\n     * @dev Called by the Vault when a user calls `IVault.exitPool` to remove liquidity from this Pool. Returns how many\\n     * tokens the Vault should deduct from the Pool's balances, as well as the amount of protocol fees the Pool owes\\n     * to the Vault. The Vault will then take tokens from the Pool's balances and send them to `recipient`,\\n     * as well as collect the reported amount in protocol fees, which the Pool should calculate based on\\n     * `protocolSwapFeePercentage`.\\n     *\\n     * Protocol fees are charged on exit events to guarantee that users exiting the Pool have paid their share.\\n     *\\n     * `sender` is the account performing the exit (typically the pool shareholder), and `recipient` is the account\\n     * to which the Vault will send the proceeds. `currentBalances` contains the total token balances for each token\\n     * the Pool registered in the Vault, in the same order that `IVault.getPoolTokens` would return.\\n     *\\n     * `lastChangeBlock` is the last block in which *any* of the Pool's registered tokens last changed its total\\n     * balance.\\n     *\\n     * `userData` contains any pool-specific instructions needed to perform the calculations, such as the type of\\n     * exit (e.g., proportional given an amount of pool shares, single-asset, multi-asset, etc.)\\n     *\\n     * Contracts implementing this function should check that the caller is indeed the Vault before performing any\\n     * state-changing operations, such as burning pool shares.\\n     */\\n    function onExitPool(\\n        bytes32 poolId,\\n        address sender,\\n        address recipient,\\n        uint256[] memory balances,\\n        uint256 lastChangeBlock,\\n        uint256 protocolSwapFeePercentage,\\n        bytes memory userData\\n    ) external returns (uint256[] memory amountsOut, uint256[] memory dueProtocolFeeAmounts);\\n}\\n\",\"keccak256\":\"0x1fdce4de26cad355f4ad93e4a5b66d5a5692c4cd2f0b6c2bb2c3aef3ee49422f\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/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;\\n\\n// Inspired by Aave Protocol's IFlashLoanReceiver.\\n\\nimport \\\"../../lib/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\",\"keccak256\":\"0x6886740dcaebfb24a25f914ce5b4299aeab3fe0cc135a1707c0fe4e3d6d02cb6\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/IGeneralPool.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;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"./IBasePool.sol\\\";\\n\\n/**\\n * @dev IPools with the General specialization setting should implement this interface.\\n *\\n * This is called by the Vault when a user calls `IVault.swap` or `IVault.batchSwap` to swap with this Pool.\\n * Returns the number of tokens the Pool will grant to the user in a 'given in' swap, or that the user will\\n * grant to the pool in a 'given out' swap.\\n *\\n * This can often be implemented by a `view` function, since many pricing algorithms don't need to track state\\n * changes in swaps. However, contracts implementing this in non-view functions should check that the caller is\\n * indeed the Vault.\\n */\\ninterface IGeneralPool is IBasePool {\\n    function onSwap(\\n        SwapRequest memory swapRequest,\\n        uint256[] memory balances,\\n        uint256 indexIn,\\n        uint256 indexOut\\n    ) external returns (uint256 amount);\\n}\\n\",\"keccak256\":\"0x7f11733a5cd8f81c123c02f79d94ead7b65217021ebddafda10e796a25e1ef41\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/IPoolSwapStructs.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;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../../lib/openzeppelin/IERC20.sol\\\";\\n\\nimport \\\"./IVault.sol\\\";\\n\\ninterface IPoolSwapStructs {\\n    // This is not really an interface - it just defines common structs used by other interfaces: IGeneralPool and\\n    // IMinimalSwapInfoPool.\\n    //\\n    // This data structure represents a request for a token swap, where `kind` indicates the swap type ('given in' or\\n    // 'given out') which indicates whether or not the amount sent by the pool is known.\\n    //\\n    // The pool receives `tokenIn` and sends `tokenOut`. `amount` is the number of `tokenIn` tokens the pool will take\\n    // in, or the number of `tokenOut` tokens the Pool will send out, depending on the given swap `kind`.\\n    //\\n    // All other fields are not strictly necessary for most swaps, but are provided to support advanced scenarios in\\n    // some Pools.\\n    //\\n    // `poolId` is the ID of the Pool involved in the swap - this is useful for Pool contracts that implement more than\\n    // one Pool.\\n    //\\n    // The meaning of `lastChangeBlock` depends on the Pool specialization:\\n    //  - Two Token or Minimal Swap Info: the last block in which either `tokenIn` or `tokenOut` changed its total\\n    //    balance.\\n    //  - General: the last block in which *any* of the Pool's registered tokens changed its total balance.\\n    //\\n    // `from` is the origin address for the funds the Pool receives, and `to` is the destination address\\n    // where the Pool sends the outgoing tokens.\\n    //\\n    // `userData` is extra data provided by the caller - typically a signature from a trusted party.\\n    struct SwapRequest {\\n        IVault.SwapKind kind;\\n        IERC20 tokenIn;\\n        IERC20 tokenOut;\\n        uint256 amount;\\n        // Misc data\\n        bytes32 poolId;\\n        uint256 lastChangeBlock;\\n        address from;\\n        address to;\\n        bytes userData;\\n    }\\n}\\n\",\"keccak256\":\"0xe32bcd1cce37949796369b0026cf5cf34eb7273fa50ac239186e8cd4b822e196\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/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;\\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\",\"keccak256\":\"0x2fe46b13b7c8bfc6f5c539c0b73d6325813f383f551b71fb6bca8dafd06964e1\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/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 \\\"../../lib/openzeppelin/IERC20.sol\\\";\\n\\nimport \\\"./IWETH.sol\\\";\\nimport \\\"./IAsset.sol\\\";\\nimport \\\"./IAuthorizer.sol\\\";\\nimport \\\"./IFlashLoanRecipient.sol\\\";\\nimport \\\"./ISignaturesValidator.sol\\\";\\nimport \\\"../ProtocolFeesCollector.sol\\\";\\n\\npragma solidity ^0.7.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 {\\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 changeAuthorizer(IAuthorizer newAuthorizer) external;\\n\\n    event AuthorizerChanged(IAuthorizer indexed oldAuthorizer, 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    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 poolId);\\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 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 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    function flashLoan(\\n        IFlashLoanRecipient recipient,\\n        IERC20[] memory tokens,\\n        uint256[] memory amounts,\\n        bytes memory userData\\n    ) external;\\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 (ProtocolFeesCollector);\\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\",\"keccak256\":\"0x9e7499e263ba0da0d97e3937f3446b74a17d14d3d2f16c47a4a5c14686c61ac0\",\"license\":\"GPL-3.0-or-later\"},\"src.sol/amm/vault/interfaces/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;\\n\\nimport \\\"../../lib/openzeppelin/IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the WETH token contract used internally for wrapping and unwrapping, to support\\n * sending and receiving ETH in joins, swaps, and internal balance deposits and withdrawals.\\n */\\ninterface IWETH is IERC20 {\\n    function deposit() external payable;\\n\\n    function withdraw(uint256 amount) external;\\n}\\n\",\"keccak256\":\"0x621a25d9e3f3a4cd9e4493ab330a50a4456b6ea8fc568911fdd5486f78a4d3ab\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}",
  "bytecode": "0x60a060405234801561001057600080fd5b50604051610a62380380610a628339818101604052602081101561003357600080fd5b50513360601b608052610053670de0b6b3a764000082101561012c610074565b61006c69010f0cf064dd5920000082111561012d610074565b6000556100d9565b816100825761008281610086565b5050565b62461bcd60e51b6000908152602060045260076024526642414c23000030600a808404818106603090810160081b95839006959095019082900491820690940160101b939093010160c81b604452606490fd5b60805160601c61096c6100f660003980610240525061096c6000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80631cb2333d1461005c5780631ff3bc6b146100765780636daccffa1461012557806377a743021461012d57806397010c6f146101dc575b600080fd5b6100646101fb565b60408051918252519081900360200190f35b6100646004803603608081101561008c57600080fd5b813591908101906040810160208201356401000000008111156100ae57600080fd5b8201836020820111156100c057600080fd5b803590602001918460208302840111640100000000831117156100e257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060200135610201565b61006461021d565b6100646004803603608081101561014357600080fd5b8135919081019060408101602082013564010000000081111561016557600080fd5b82018360208201111561017757600080fd5b8035906020019184602083028401116401000000008311171561019957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060200135610223565b6101f9600480360360208110156101f257600080fd5b5035610235565b005b60005481565b6000806102136000548686868a6102a1565b9695505050505050565b60005490565b6000806102136000548686868a610379565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461029c5760405162461bcd60e51b81526004018080602001828103825260228152602001806109156022913960400191505060405180910390fd5b600055565b6000806102ae8787610403565b90506102d6838786815181106102c057fe5b602002602001015161057990919063ffffffff16565b8685815181106102e257fe5b60200260200101818152505060006102fc8888848961058f565b90506103248488878151811061030e57fe5b602002602001015161074890919063ffffffff16565b87868151811061033057fe5b60200260200101818152505061036d600161036789898151811061035057fe5b60200260200101518461057990919063ffffffff16565b90610748565b98975050505050505050565b6000806103868787610403565b90506103988387878151811061030e57fe5b8686815181106103a457fe5b60200260200101818152505060006103be8888848861058f565b90506103d0848888815181106102c057fe5b8787815181106103dc57fe5b60200260200101818152505061036d60016103fd838a89815181106102c057fe5b90610579565b80516000908190815b818110156104445761043a85828151811061042357fe5b60200260200101518461074890919063ffffffff16565b925060010161040c565b508161045557600092505050610573565b600082816104638885610761565b905060005b60ff81101561056a576000610491868a60008151811061048457fe5b6020026020010151610761565b905060015b868110156104ca576104c06104ba6104b4848d858151811061048457fe5b89610761565b86610785565b9150600101610496565b508394506105246104fa6104e76104e1868b610761565b84610761565b6103676104f48a89610761565b88610761565b61051f61051161050b876001610579565b85610761565b6103676104b48b6001610748565b610785565b93508484111561054a57600161053a8587610579565b11610545575061056a565b610561565b60016105568686610579565b11610561575061056a565b50600101610468565b50909450505050505b92915050565b60006105898383111560016107b8565b50900390565b60008061059d868651610761565b90506000856000815181106105ae57fe5b6020026020010151905060006105cc87518860008151811061048457fe5b905060015b8751811015610618576105fd6105f76105f0848b858151811061048457fe5b8a51610761565b886107ca565b915061060e88828151811061042357fe5b92506001016105d1565b5061063f87868151811061062857fe5b60200260200101518361057990919063ffffffff16565b915060006106566106508889610761565b85610785565b9050610688826106828a898151811061066b57fe5b6020026020010151846107ea90919063ffffffff16565b9061082e565b905060006106a06106998987610879565b8590610748565b90506000806106c06106b28b85610748565b610682866103678e806107ea565b905060005b60ff811015610738578192506106f56106e78c6103fd87610367876002610761565b6106828761036786806107ea565b91508282111561071a57600161070b8385610579565b1161071557610738565b610730565b60016107268484610579565b1161073057610738565b6001016106c5565b509b9a5050505050505050505050565b600082820161075a84821015836107b8565b9392505050565b600082820261075a84158061077e57508385838161077b57fe5b04145b60036107b8565b600061079482151560046107b8565b826107a157506000610573565b8160018403816107ad57fe5b046001019050610573565b816107c6576107c6816108c1565b5050565b60006107d982151560046107b8565b8183816107e257fe5b049392505050565b600082820261080484158061077e57508385838161077b57fe5b80610813576000915050610573565b670de0b6b3a764000060001982015b04600101915050610573565b600061083d82151560046107b8565b8261084a57506000610573565b670de0b6b3a76400008381029061086d9085838161086457fe5b041460056107b8565b82600182038161082257fe5b600061088882151560046107b8565b8261089557506000610573565b670de0b6b3a7640000838102906108af9085838161086457fe5b8281816108b857fe5b04915050610573565b62461bcd60e51b6000908152602060045260076024526642414c23000030600a808404818106603090810160081b95839006959095019082900491820690940160101b939093010160c81b604452606490fdfe4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6e2ea26469706673582212209cb985ae52e8ec76288dbf80f8dd131ac7839088dfa76f3e69293ce96a8bde7c64736f6c63430007010033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80631cb2333d1461005c5780631ff3bc6b146100765780636daccffa1461012557806377a743021461012d57806397010c6f146101dc575b600080fd5b6100646101fb565b60408051918252519081900360200190f35b6100646004803603608081101561008c57600080fd5b813591908101906040810160208201356401000000008111156100ae57600080fd5b8201836020820111156100c057600080fd5b803590602001918460208302840111640100000000831117156100e257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060200135610201565b61006461021d565b6100646004803603608081101561014357600080fd5b8135919081019060408101602082013564010000000081111561016557600080fd5b82018360208201111561017757600080fd5b8035906020019184602083028401116401000000008311171561019957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060200135610223565b6101f9600480360360208110156101f257600080fd5b5035610235565b005b60005481565b6000806102136000548686868a6102a1565b9695505050505050565b60005490565b6000806102136000548686868a610379565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461029c5760405162461bcd60e51b81526004018080602001828103825260228152602001806109156022913960400191505060405180910390fd5b600055565b6000806102ae8787610403565b90506102d6838786815181106102c057fe5b602002602001015161057990919063ffffffff16565b8685815181106102e257fe5b60200260200101818152505060006102fc8888848961058f565b90506103248488878151811061030e57fe5b602002602001015161074890919063ffffffff16565b87868151811061033057fe5b60200260200101818152505061036d600161036789898151811061035057fe5b60200260200101518461057990919063ffffffff16565b90610748565b98975050505050505050565b6000806103868787610403565b90506103988387878151811061030e57fe5b8686815181106103a457fe5b60200260200101818152505060006103be8888848861058f565b90506103d0848888815181106102c057fe5b8787815181106103dc57fe5b60200260200101818152505061036d60016103fd838a89815181106102c057fe5b90610579565b80516000908190815b818110156104445761043a85828151811061042357fe5b60200260200101518461074890919063ffffffff16565b925060010161040c565b508161045557600092505050610573565b600082816104638885610761565b905060005b60ff81101561056a576000610491868a60008151811061048457fe5b6020026020010151610761565b905060015b868110156104ca576104c06104ba6104b4848d858151811061048457fe5b89610761565b86610785565b9150600101610496565b508394506105246104fa6104e76104e1868b610761565b84610761565b6103676104f48a89610761565b88610761565b61051f61051161050b876001610579565b85610761565b6103676104b48b6001610748565b610785565b93508484111561054a57600161053a8587610579565b11610545575061056a565b610561565b60016105568686610579565b11610561575061056a565b50600101610468565b50909450505050505b92915050565b60006105898383111560016107b8565b50900390565b60008061059d868651610761565b90506000856000815181106105ae57fe5b6020026020010151905060006105cc87518860008151811061048457fe5b905060015b8751811015610618576105fd6105f76105f0848b858151811061048457fe5b8a51610761565b886107ca565b915061060e88828151811061042357fe5b92506001016105d1565b5061063f87868151811061062857fe5b60200260200101518361057990919063ffffffff16565b915060006106566106508889610761565b85610785565b9050610688826106828a898151811061066b57fe5b6020026020010151846107ea90919063ffffffff16565b9061082e565b905060006106a06106998987610879565b8590610748565b90506000806106c06106b28b85610748565b610682866103678e806107ea565b905060005b60ff811015610738578192506106f56106e78c6103fd87610367876002610761565b6106828761036786806107ea565b91508282111561071a57600161070b8385610579565b1161071557610738565b610730565b60016107268484610579565b1161073057610738565b6001016106c5565b509b9a5050505050505050505050565b600082820161075a84821015836107b8565b9392505050565b600082820261075a84158061077e57508385838161077b57fe5b04145b60036107b8565b600061079482151560046107b8565b826107a157506000610573565b8160018403816107ad57fe5b046001019050610573565b816107c6576107c6816108c1565b5050565b60006107d982151560046107b8565b8183816107e257fe5b049392505050565b600082820261080484158061077e57508385838161077b57fe5b80610813576000915050610573565b670de0b6b3a764000060001982015b04600101915050610573565b600061083d82151560046107b8565b8261084a57506000610573565b670de0b6b3a76400008381029061086d9085838161086457fe5b041460056107b8565b82600182038161082257fe5b600061088882151560046107b8565b8261089557506000610573565b670de0b6b3a7640000838102906108af9085838161086457fe5b8281816108b857fe5b04915050610573565b62461bcd60e51b6000908152602060045260076024526642414c23000030600a808404818106603090810160081b95839006959095019082900491820690940160101b939093010160c81b604452606490fdfe4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6e2ea26469706673582212209cb985ae52e8ec76288dbf80f8dd131ac7839088dfa76f3e69293ce96a8bde7c64736f6c63430007010033",
  "devdoc": {
    "kind": "dev",
    "methods": {},
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 16,
        "contract": "src.sol/amm/StableSwap.sol:StableSwap",
        "label": "amplificationParameter",
        "offset": 0,
        "slot": "0",
        "type": "t_uint256"
      }
    ],
    "types": {
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}