diff --git a/cache/solidity-files-cache.json b/cache/solidity-files-cache.json
new file mode 100644
index 0000000..6e6ec61
--- /dev/null
+++ b/cache/solidity-files-cache.json
@@ -0,0 +1 @@
+{"_format":"","paths":{"artifacts":"out","build_infos":"out/build-info","sources":"src","tests":"test","scripts":"script","libraries":["lib"]},"files":{"test/TychoRouter.t.sol":{"lastModificationDate":1737991455132,"contentHash":"7215ee9c7d9dc229d2921a40e899ec5f","sourceName":"test/TychoRouter.t.sol","imports":[],"versionRequirement":null,"artifacts":{},"seenByCompiler":true}},"builds":[],"profiles":{"default":{"solc":{"optimizer":{"enabled":false,"runs":200},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"outputSelection":{"*":{"*":["abi","evm.bytecode.object","evm.bytecode.sourceMap","evm.bytecode.linkReferences","evm.deployedBytecode.object","evm.deployedBytecode.sourceMap","evm.deployedBytecode.linkReferences","evm.deployedBytecode.immutableReferences","evm.methodIdentifiers","metadata"]}},"evmVersion":"cancun","viaIR":false,"libraries":{}},"vyper":{"evmVersion":"cancun","outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode"]}}}}}}
\ No newline at end of file
diff --git a/foundry/lib/balancer-labs/v2-interfaces/CHANGELOG.md b/foundry/lib/balancer-labs/v2-interfaces/CHANGELOG.md
new file mode 100644
index 0000000..2343f27
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/CHANGELOG.md
@@ -0,0 +1,57 @@
+# Changelog
+
+## 0.4.0 (20223-03-15)
+
+- Added `IERC4626`.
+- Added `IChildChainGauge`.
+- Added `ILMGetters`.
+
+### Breaking changes
+
+- Removed `IBaseGaugeFactory`.
+- Refactor: renamed `IBalancerMinter` to `IMainnetBalancerMinter`.
+ - `IMainnetBalancerMinter` now implements reduced version of previous `IBalancerMinter` and `ILMGetters`.
+
+## 0.3.0 (20223-02-08)
+
+### New Features
+
+- Added `checkpointGaugesOfTypeAboveRelativeWeight` to `IL2GaugeCheckpointer`.
+- Added `IComposableStablePoolRates`.
+- Added `IProtocolFeeCache`.
+- Added `setTargets` and `setSwapFeePercentage` to `ILinearPool`.
+
+### Breaking changes
+
+- `IL2GaugeCheckpointer`: `getGaugeAt` renamed to `getGaugeAtIndex`.
+
+## 0.2.1 (2022-12-12)
+
+### Misc
+
+- Added examples to readme.
+
+## 0.2.0 (2022-12-01)
+
+### New Interfaces
+
+- Added `IProtocolFeeSplitter`.
+- Added `IL2GaugeCheckpointer`.
+- Added `IAuthorizerAdaptorEntrypoint`.
+- Added `IRateProviderPool`.
+- Added `IVersion`.
+- Added `IFactoryCreatedPoolVersion`.
+- Added `IRecoveryModeHelper`.
+
+### New Features
+
+- Extended the valid compiler version range to any of the 0.7.x and 0.8.x line.
+
+### Breaking Changes
+
+- Removed `IAssetManager`, which was unused.
+- `IGaugeAdder`: authorizer adaptor getter replaced with authorizer adaptor entrypoint getter.
+
+## 0.1.0 (2022-10-25)
+
+- Initial release.
diff --git a/foundry/lib/balancer-labs/v2-interfaces/README.md b/foundry/lib/balancer-labs/v2-interfaces/README.md
new file mode 100644
index 0000000..f6eb9ad
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/README.md
@@ -0,0 +1,139 @@
+#
+
+# Balancer V2 Interfaces
+
+[](https://www.npmjs.org/package/@balancer-labs/v2-interfaces)
+
+This package contains interfaces used in dependent packages, which makes building systems that interact with Balancer contracts simpler, as the implementation information is not included.
+
+## Overview
+
+### Installation
+
+```console
+$ npm install @balancer-labs/v2-interfaces
+```
+
+### Usage
+
+This package can be used in multiple ways, including interacting with already deployed Pools, or performing local testing. It contains all interfaces used in the system, from the foundational [Vault](contracts/vault/IVault.sol) to very specific contracts (e.g., [Optimism Gas Limit Provider](contracts/liquidity-mining/IOptimismGasLimitProvider.sol)).
+
+The following are a couple code samples to help get you started. To get the address of deployed contracts in both production and test networks, see [`v2-deployments`](../deployments).
+
+Sample contract that joins a Balancer Pool:
+
+````solidity
+pragma solidity ^0.7.0;
+
+// Import Vault interface, error messages, and library for decoding join/exit data.
+import "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/BalancerErrors.sol";
+import "@balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol";
+import "@balancer-labs/v2-interfaces/contracts/pool-weighted/WeightedPoolUserData.sol";
+import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
+import "@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol";
+
+// Import ERC20Helpers for `_asIAsset`
+import "@balancer-labs/v2-solidity-utils/contracts/helpers/ERC20Helpers.sol";
+
+contract JoinBalancerPool {
+ IVault private constant vault = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";
+
+ function joinBalancerPool(bytes32 poolId, address sender, address recipient, uint256[] memory amountsIn, uint256 minBptAmountOut) external {
+ (IERC20[] memory tokens, , ) = vault.getPoolTokens(poolId);
+
+ // Use BalancerErrors to validate input
+ _require(amountsIn.length == tokens.length, Errors.INPUT_LENGTH_MISMATCH);
+
+ // Encode the userData for a multi-token join
+ bytes memory userData = abi.encode(WeightedPoolUserData.JoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, amountsIn, minBptAmountOut);
+
+ IVault.JoinPoolRequest memory request = IVault.JoinPoolRequest({
+ assets: _asIAsset(tokens),
+ maxAmountsIn: amountsIn,
+ userData: userData,
+ fromInternalBalance: false
+ });
+
+ // Call the Vault to join the pool
+ vault.joinPool(poolId, sender, recipient, request);
+ }
+
+ ...
+}
+```
+
+Sample contract that performs Internal Balance deposits:
+
+```solidity
+pragma solidity ^0.7.0;
+
+import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
+
+contract SimpleDepositor {
+ IVault private constant vault = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";
+
+ function depositFunds(
+ IERC20[] memory tokens,
+ uint256[] memory amounts,
+ ) external {
+ IVault.UserBalanceOp[] memory ops = new IVault.UserBalanceOp[](tokens.length);
+
+ for (uint256 i = 0; i < tokens.length; ++i) {
+ ops[i] = IVault.UserBalanceOp({
+ kind: IVault.UserBalanceOpKind.DEPOSIT_INTERNAL,
+ asset: IAsset(tokens[i]),
+ amount: amounts[i],
+ sender: address(this),
+ recipient: address(this)
+ });
+ }
+
+ vault.manageUserBalance(ops);
+ }
+}
+````
+
+Sample contract that performs Flash Loans:
+
+```solidity
+pragma solidity ^0.7.0;
+
+import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
+import "@balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol";
+
+contract FlashLoanRecipient is IFlashLoanRecipient {
+ IVault private constant vault = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";
+
+ function makeFlashLoan(
+ IERC20[] memory tokens,
+ uint256[] memory amounts,
+ bytes memory userData
+ ) external {
+ vault.flashLoan(this, tokens, amounts, userData);
+ }
+
+ function receiveFlashLoan(
+ IERC20[] memory tokens,
+ uint256[] memory amounts,
+ uint256[] memory feeAmounts,
+ bytes memory userData
+ ) external override {
+ require(msg.sender == vault);
+ ...
+ }
+}
+```
+
+### Notes
+
+In addition to interfaces, it also includes a small number of libraries that encapsulate enum types for particular pools (e.g., [StablePoolUserData](contracts/pool-stable/StablePoolUserData.sol), and functions for working with encoding and decoding `userData`. (See the `balancer-js` package for TypeScript versions of these utilities.)
+
+One of the most commonly included libraries is [BalancerErrors](contracts/solidity-utils/helpers/BalancerErrors.sol). To save bytecode, Balancer V2 does not use the standard `require(, 'error string')`. Instead, BalancerErrors defines `_require` and `_revert` functions. These take a numerical constant instead of a string, and return a fixed-length code, which can be converted to plain text using TypeScript utilities.
+
+## Licensing
+
+[GNU General Public License Version 3 (GPL v3)](../../LICENSE).
+
+```
+
+```
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/distributors/IDistributorCallback.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/distributors/IDistributorCallback.sol
new file mode 100644
index 0000000..f656ebf
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/distributors/IDistributorCallback.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IDistributorCallback {
+ function distributorCallback(bytes calldata callbackData) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IArbitrumFeeProvider.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IArbitrumFeeProvider.sol
new file mode 100644
index 0000000..951e4a1
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IArbitrumFeeProvider.sol
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IArbitrumFeeProvider {
+ function getArbitrumFees()
+ external
+ view
+ returns (
+ uint256 gasLimit,
+ uint256 gasPrice,
+ uint256 maxSubmissionCost
+ );
+
+ function setArbitrumFees(
+ uint64 gasLimit,
+ uint64 gasPrice,
+ uint64 maxSubmissionCost
+ ) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IAuthorizerAdaptor.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IAuthorizerAdaptor.sol
new file mode 100644
index 0000000..25e4ffb
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IAuthorizerAdaptor.sol
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/helpers/IAuthentication.sol";
+import "../vault/IVault.sol";
+
+interface IAuthorizerAdaptor is IAuthentication {
+ /**
+ * @notice Returns the Balancer Vault
+ */
+ function getVault() external view returns (IVault);
+
+ /**
+ * @notice Returns the Authorizer
+ */
+ function getAuthorizer() external view returns (IAuthorizer);
+
+ /**
+ * @notice Performs an arbitrary function call on a target contract, provided the caller is authorized to do so.
+ * @param target - Address of the contract to be called
+ * @param data - Calldata to be sent to the target contract
+ * @return The bytes encoded return value from the performed function call
+ */
+ function performAction(address target, bytes calldata data) external payable returns (bytes memory);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IAuthorizerAdaptorEntrypoint.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IAuthorizerAdaptorEntrypoint.sol
new file mode 100644
index 0000000..b77db5b
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IAuthorizerAdaptorEntrypoint.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "./IAuthorizerAdaptor.sol";
+
+/**
+ * @notice Interface for `AuthorizerAdaptorEntrypoint`.
+ */
+interface IAuthorizerAdaptorEntrypoint is IAuthorizerAdaptor {
+ /**
+ * @notice Returns the Authorizer Adaptor
+ */
+ function getAuthorizerAdaptor() external view returns (IAuthorizerAdaptor);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerMinter.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerMinter.sol
new file mode 100644
index 0000000..9e6fbca
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerMinter.sol
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+/**
+ * @dev Base minter interface, applicable to Mainnet minter or L2 pseudo minters.
+ */
+interface IBalancerMinter {
+ event Minted(address indexed recipient, address gauge, uint256 minted);
+
+ /**
+ * @notice Returns the address of the Balancer Governance Token
+ */
+ function getBalancerToken() external view returns (IERC20);
+
+ /**
+ * @notice Mint everything which belongs to `msg.sender` and send to them
+ * @param gauge `LiquidityGauge` address to get mintable amount from
+ */
+ function mint(address gauge) external returns (uint256);
+
+ /**
+ * @notice Mint everything which belongs to `msg.sender` across multiple gauges
+ * @param gauges List of `LiquidityGauge` addresses
+ */
+ function mintMany(address[] calldata gauges) external returns (uint256);
+
+ /**
+ * @notice Mint tokens for `user`
+ * @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf
+ * @param gauge `LiquidityGauge` address to get mintable amount from
+ * @param user Address to mint to
+ */
+ function mintFor(address gauge, address user) external returns (uint256);
+
+ /**
+ * @notice Mint tokens for `user` across multiple gauges
+ * @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf
+ * @param gauges List of `LiquidityGauge` addresses
+ * @param user Address to mint to
+ */
+ function mintManyFor(address[] calldata gauges, address user) external returns (uint256);
+
+ /**
+ * @notice The total number of tokens minted for `user` from `gauge`
+ */
+ function minted(address user, address gauge) external view returns (uint256);
+
+ /**
+ * @notice Whether `minter` is approved to mint tokens for `user`
+ */
+ function getMinterApproval(address minter, address user) external view returns (bool);
+
+ /**
+ * @notice Set whether `minter` is approved to mint tokens on your behalf
+ */
+ function setMinterApproval(address minter, bool approval) external;
+
+ /**
+ * @notice Set whether `minter` is approved to mint tokens on behalf of `user`, who has signed a message authorizing
+ * them.
+ */
+ function setMinterApprovalWithSignature(
+ address minter,
+ bool approval,
+ address user,
+ uint256 deadline,
+ uint8 v,
+ bytes32 r,
+ bytes32 s
+ ) external;
+
+ // The below functions are near-duplicates of functions available above.
+ // They are included for ABI compatibility with snake_casing as used in vyper contracts.
+ // solhint-disable func-name-mixedcase
+
+ /**
+ * @notice Whether `minter` is approved to mint tokens for `user`
+ */
+ function allowed_to_mint_for(address minter, address user) external view returns (bool);
+
+ /**
+ * @notice Mint everything which belongs to `msg.sender` across multiple gauges
+ * @dev This function is not recommended as `mintMany()` is more flexible and gas efficient
+ * @param gauges List of `LiquidityGauge` addresses
+ */
+ function mint_many(address[8] calldata gauges) external;
+
+ /**
+ * @notice Mint tokens for `user`
+ * @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf
+ * @param gauge `LiquidityGauge` address to get mintable amount from
+ * @param user Address to mint to
+ */
+ function mint_for(address gauge, address user) external;
+
+ /**
+ * @notice Toggle whether `minter` is approved to mint tokens for `user`
+ */
+ function toggle_approve_mint(address minter) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerToken.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerToken.sol
new file mode 100644
index 0000000..9a60577
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerToken.sol
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface IBalancerToken is IERC20 {
+ function mint(address to, uint256 amount) external;
+
+ function getRoleMemberCount(bytes32 role) external view returns (uint256);
+
+ function getRoleMember(bytes32 role, uint256 index) external view returns (address);
+
+ function hasRole(bytes32 role, address account) external view returns (bool);
+
+ function getRoleAdmin(bytes32 role) external view returns (bytes32);
+
+ function grantRole(bytes32 role, address account) external;
+
+ function revokeRole(bytes32 role, address account) external;
+
+ // solhint-disable-next-line func-name-mixedcase
+ function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
+
+ // solhint-disable-next-line func-name-mixedcase
+ function MINTER_ROLE() external view returns (bytes32);
+
+ // solhint-disable-next-line func-name-mixedcase
+ function SNAPSHOT_ROLE() external view returns (bytes32);
+
+ function snapshot() external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerTokenAdmin.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerTokenAdmin.sol
new file mode 100644
index 0000000..3334591
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IBalancerTokenAdmin.sol
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/helpers/IAuthentication.sol";
+
+import "./IBalancerToken.sol";
+
+interface IBalancerTokenAdmin is IAuthentication {
+ // solhint-disable func-name-mixedcase
+ function INITIAL_RATE() external view returns (uint256);
+
+ function RATE_REDUCTION_TIME() external view returns (uint256);
+
+ function RATE_REDUCTION_COEFFICIENT() external view returns (uint256);
+
+ function RATE_DENOMINATOR() external view returns (uint256);
+
+ // solhint-enable func-name-mixedcase
+
+ /**
+ * @notice Returns the address of the Balancer Governance Token
+ */
+ function getBalancerToken() external view returns (IBalancerToken);
+
+ function activate() external;
+
+ function rate() external view returns (uint256);
+
+ function startEpochTimeWrite() external returns (uint256);
+
+ function mint(address to, uint256 amount) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainGauge.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainGauge.sol
new file mode 100644
index 0000000..d4df179
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainGauge.sol
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../pool-utils/IVersion.sol";
+import "./ILiquidityGaugeFactory.sol";
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase
+// solhint-disable func-param-name-mixedcase
+
+interface IChildChainGauge is IVersion {
+ /**
+ * @notice Proxy constructor.
+ * @param lpToken Pool allowed to stake in this gauge.
+ * @param version Gauge version string identifier.
+ */
+ function initialize(address lpToken, string memory version) external;
+
+ /**
+ * @notice Returns BAL liquidity emissions calculated during checkpoints for the given user.
+ * @param user User address.
+ * @return uint256 BAL amount to issue for the address.
+ */
+ function integrate_fraction(address user) external view returns (uint256);
+
+ /**
+ * @notice Records a checkpoint for a given user.
+ * @param user User address.
+ * @return bool Always true.
+ */
+ function user_checkpoint(address user) external returns (bool);
+
+ /**
+ * @notice Returns gauge factory address.
+ */
+ function factory() external view returns (ILiquidityGaugeFactory);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainLiquidityGaugeFactory.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainLiquidityGaugeFactory.sol
new file mode 100644
index 0000000..7f6fc89
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainLiquidityGaugeFactory.sol
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "./IChildChainStreamer.sol";
+import "./ILiquidityGauge.sol";
+import "./ILiquidityGaugeFactory.sol";
+import "./IRewardsOnlyGauge.sol";
+
+interface IChildChainLiquidityGaugeFactory is ILiquidityGaugeFactory {
+ event RewardsOnlyGaugeCreated(address indexed gauge, address indexed pool, address streamer);
+
+ /**
+ * @notice Returns the address of the implementation used for gauge deployments.
+ */
+ function getGaugeImplementation() external view returns (ILiquidityGauge);
+
+ /**
+ * @notice Returns the address of the implementation used for streamer deployments.
+ */
+ function getChildChainStreamerImplementation() external view returns (IChildChainStreamer);
+
+ /**
+ * @notice Returns the address of the gauge belonging to `pool`.
+ */
+ function getPoolGauge(address pool) external view returns (ILiquidityGauge);
+
+ /**
+ * @notice Returns the address of the streamer belonging to `gauge`.
+ */
+ function getGaugeStreamer(address gauge) external view returns (address);
+
+ /**
+ * @notice Returns true if `streamer` was created by this factory.
+ */
+ function isStreamerFromFactory(address streamer) external view returns (bool);
+
+ /**
+ * @notice Returns the address of the pool which `gauge` belongs.
+ */
+ function getGaugePool(address gauge) external view returns (IERC20);
+
+ /**
+ * @notice Returns the address of the streamer belonging to `pool`'s gauge.
+ */
+ function getPoolStreamer(address pool) external view returns (address);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainStreamer.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainStreamer.sol
new file mode 100644
index 0000000..93f8f25
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IChildChainStreamer.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase
+
+interface IChildChainStreamer {
+ function initialize(address gauge) external;
+
+ function get_reward() external;
+
+ function reward_tokens(uint256 index) external view returns (IERC20);
+
+ function add_reward(
+ IERC20 rewardToken,
+ address distributor,
+ uint256 duration
+ ) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IFeeDistributor.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IFeeDistributor.sol
new file mode 100644
index 0000000..42e0a6a
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IFeeDistributor.sol
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+import "./IVotingEscrow.sol";
+
+/**
+ * @title Fee Distributor
+ * @notice Distributes any tokens transferred to the contract (e.g. Protocol fees and any BAL emissions) among veBAL
+ * holders proportionally based on a snapshot of the week at which the tokens are sent to the FeeDistributor contract.
+ * @dev Supports distributing arbitrarily many different tokens. In order to start distributing a new token to veBAL
+ * holders simply transfer the tokens to the `FeeDistributor` contract and then call `checkpointToken`.
+ */
+interface IFeeDistributor {
+ event TokenCheckpointed(IERC20 token, uint256 amount, uint256 lastCheckpointTimestamp);
+ event TokensClaimed(address user, IERC20 token, uint256 amount, uint256 userTokenTimeCursor);
+
+ /**
+ * @notice Returns the VotingEscrow (veBAL) token contract
+ */
+ function getVotingEscrow() external view returns (IVotingEscrow);
+
+ /**
+ * @notice Returns the global time cursor representing the most earliest uncheckpointed week.
+ */
+ function getTimeCursor() external view returns (uint256);
+
+ /**
+ * @notice Returns the user-level time cursor representing the most earliest uncheckpointed week.
+ * @param user - The address of the user to query.
+ */
+ function getUserTimeCursor(address user) external view returns (uint256);
+
+ /**
+ * @notice Returns the token-level time cursor storing the timestamp at up to which tokens have been distributed.
+ * @param token - The ERC20 token address to query.
+ */
+ function getTokenTimeCursor(IERC20 token) external view returns (uint256);
+
+ /**
+ * @notice Returns the user-level time cursor storing the timestamp of the latest token distribution claimed.
+ * @param user - The address of the user to query.
+ * @param token - The ERC20 token address to query.
+ */
+ function getUserTokenTimeCursor(address user, IERC20 token) external view returns (uint256);
+
+ /**
+ * @notice Returns the user's cached balance of veBAL as of the provided timestamp.
+ * @dev Only timestamps which fall on Thursdays 00:00:00 UTC will return correct values.
+ * This function requires `user` to have been checkpointed past `timestamp` so that their balance is cached.
+ * @param user - The address of the user of which to read the cached balance of.
+ * @param timestamp - The timestamp at which to read the `user`'s cached balance at.
+ */
+ function getUserBalanceAtTimestamp(address user, uint256 timestamp) external view returns (uint256);
+
+ /**
+ * @notice Returns the cached total supply of veBAL as of the provided timestamp.
+ * @dev Only timestamps which fall on Thursdays 00:00:00 UTC will return correct values.
+ * This function requires the contract to have been checkpointed past `timestamp` so that the supply is cached.
+ * @param timestamp - The timestamp at which to read the cached total supply at.
+ */
+ function getTotalSupplyAtTimestamp(uint256 timestamp) external view returns (uint256);
+
+ /**
+ * @notice Returns the FeeDistributor's cached balance of `token`.
+ */
+ function getTokenLastBalance(IERC20 token) external view returns (uint256);
+
+ /**
+ * @notice Returns the amount of `token` which the FeeDistributor received in the week beginning at `timestamp`.
+ * @param token - The ERC20 token address to query.
+ * @param timestamp - The timestamp corresponding to the beginning of the week of interest.
+ */
+ function getTokensDistributedInWeek(IERC20 token, uint256 timestamp) external view returns (uint256);
+
+ // Depositing
+
+ /**
+ * @notice Deposits tokens to be distributed in the current week.
+ * @dev Sending tokens directly to the FeeDistributor instead of using `depositTokens` may result in tokens being
+ * retroactively distributed to past weeks, or for the distribution to carry over to future weeks.
+ *
+ * If for some reason `depositTokens` cannot be called, in order to ensure that all tokens are correctly distributed
+ * manually call `checkpointToken` before and after the token transfer.
+ * @param token - The ERC20 token address to distribute.
+ * @param amount - The amount of tokens to deposit.
+ */
+ function depositToken(IERC20 token, uint256 amount) external;
+
+ /**
+ * @notice Deposits tokens to be distributed in the current week.
+ * @dev A version of `depositToken` which supports depositing multiple `tokens` at once.
+ * See `depositToken` for more details.
+ * @param tokens - An array of ERC20 token addresses to distribute.
+ * @param amounts - An array of token amounts to deposit.
+ */
+ function depositTokens(IERC20[] calldata tokens, uint256[] calldata amounts) external;
+
+ // Checkpointing
+
+ /**
+ * @notice Caches the total supply of veBAL at the beginning of each week.
+ * This function will be called automatically before claiming tokens to ensure the contract is properly updated.
+ */
+ function checkpoint() external;
+
+ /**
+ * @notice Caches the user's balance of veBAL at the beginning of each week.
+ * This function will be called automatically before claiming tokens to ensure the contract is properly updated.
+ * @param user - The address of the user to be checkpointed.
+ */
+ function checkpointUser(address user) external;
+
+ /**
+ * @notice Assigns any newly-received tokens held by the FeeDistributor to weekly distributions.
+ * @dev Any `token` balance held by the FeeDistributor above that which is returned by `getTokenLastBalance`
+ * will be distributed evenly across the time period since `token` was last checkpointed.
+ *
+ * This function will be called automatically before claiming tokens to ensure the contract is properly updated.
+ * @param token - The ERC20 token address to be checkpointed.
+ */
+ function checkpointToken(IERC20 token) external;
+
+ /**
+ * @notice Assigns any newly-received tokens held by the FeeDistributor to weekly distributions.
+ * @dev A version of `checkpointToken` which supports checkpointing multiple tokens.
+ * See `checkpointToken` for more details.
+ * @param tokens - An array of ERC20 token addresses to be checkpointed.
+ */
+ function checkpointTokens(IERC20[] calldata tokens) external;
+
+ // Claiming
+
+ /**
+ * @notice Claims all pending distributions of the provided token for a user.
+ * @dev It's not necessary to explicitly checkpoint before calling this function, it will ensure the FeeDistributor
+ * is up to date before calculating the amount of tokens to be claimed.
+ * @param user - The user on behalf of which to claim.
+ * @param token - The ERC20 token address to be claimed.
+ * @return The amount of `token` sent to `user` as a result of claiming.
+ */
+ function claimToken(address user, IERC20 token) external returns (uint256);
+
+ /**
+ * @notice Claims a number of tokens on behalf of a user.
+ * @dev A version of `claimToken` which supports claiming multiple `tokens` on behalf of `user`.
+ * See `claimToken` for more details.
+ * @param user - The user on behalf of which to claim.
+ * @param tokens - An array of ERC20 token addresses to be claimed.
+ * @return An array of the amounts of each token in `tokens` sent to `user` as a result of claiming.
+ */
+ function claimTokens(address user, IERC20[] calldata tokens) external returns (uint256[] memory);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IGaugeAdder.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IGaugeAdder.sol
new file mode 100644
index 0000000..5966841
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IGaugeAdder.sol
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "./IAuthorizerAdaptorEntrypoint.sol";
+import "./IGaugeController.sol";
+import "./ILiquidityGauge.sol";
+import "./ILiquidityGaugeFactory.sol";
+import "./IStakingLiquidityGauge.sol";
+
+interface IGaugeAdder is IAuthentication {
+ enum GaugeType { LiquidityMiningCommittee, veBAL, Ethereum, Polygon, Arbitrum, Optimism, Gnosis, ZKSync }
+
+ event GaugeFactoryAdded(GaugeType indexed gaugeType, ILiquidityGaugeFactory gaugeFactory);
+
+ /**
+ * @notice Returns the address of the Authorizer adaptor entrypoint contract.
+ */
+ function getAuthorizerAdaptorEntrypoint() external view returns (IAuthorizerAdaptorEntrypoint);
+
+ /**
+ * @notice Returns the address of the Gauge Controller
+ */
+ function getGaugeController() external view returns (IGaugeController);
+
+ /**
+ * @notice Returns the `index`'th factory for gauge type `gaugeType`
+ */
+ function getFactoryForGaugeType(GaugeType gaugeType, uint256 index) external view returns (address);
+
+ /**
+ * @notice Returns the number of factories for gauge type `gaugeType`
+ */
+ function getFactoryForGaugeTypeCount(GaugeType gaugeType) external view returns (uint256);
+
+ /**
+ * @notice Returns whether `gauge` has been deployed by one of the listed factories for the gauge type `gaugeType`
+ */
+ function isGaugeFromValidFactory(address gauge, GaugeType gaugeType) external view returns (bool);
+
+ /**
+ * @notice Adds a new gauge to the GaugeController for the "Ethereum" type.
+ */
+ function addEthereumGauge(IStakingLiquidityGauge gauge) external;
+
+ /**
+ * @notice Adds a new gauge to the GaugeController for the "Polygon" type.
+ * This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
+ * It should not be called with the address of the gauge which is deployed on Polygon
+ */
+ function addPolygonGauge(address rootGauge) external;
+
+ /**
+ * @notice Adds a new gauge to the GaugeController for the "Arbitrum" type.
+ * This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
+ * It should not be called with the address of the gauge which is deployed on Arbitrum
+ */
+ function addArbitrumGauge(address rootGauge) external;
+
+ /**
+ * @notice Adds a new gauge to the GaugeController for the "Optimism" type.
+ * This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
+ * It should not be called with the address of the gauge which is deployed on Optimism.
+ */
+ function addOptimismGauge(address rootGauge) external;
+
+ /**
+ * @notice Adds a new gauge to the GaugeController for the "Gnosis" type.
+ * This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
+ * It should not be called with the address of the gauge which is deployed on Gnosis Chain.
+ */
+ function addGnosisGauge(address rootGauge) external;
+
+ /**
+ * @notice Adds a new gauge to the GaugeController for the "ZKSync" type.
+ * This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
+ * It should not be called with the address of the gauge which is deployed on ZKSync.
+ */
+ function addZKSyncGauge(address rootGauge) external;
+
+ /**
+ * @notice Adds `factory` as an allowlisted factory contract for gauges with type `gaugeType`.
+ */
+ function addGaugeFactory(ILiquidityGaugeFactory factory, GaugeType gaugeType) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IGaugeController.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IGaugeController.sol
new file mode 100644
index 0000000..88390fb
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IGaugeController.sol
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+import "./IAuthorizerAdaptor.sol";
+import "./IVotingEscrow.sol";
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase
+
+interface IGaugeController {
+ function checkpoint_gauge(address gauge) external;
+
+ function gauge_relative_weight(address gauge, uint256 time) external view returns (uint256);
+
+ function voting_escrow() external view returns (IVotingEscrow);
+
+ function token() external view returns (IERC20);
+
+ function add_type(string calldata name, uint256 weight) external;
+
+ function change_type_weight(int128 typeId, uint256 weight) external;
+
+ function add_gauge(address gauge, int128 gaugeType) external;
+
+ function n_gauge_types() external view returns (int128);
+
+ function gauge_types(address gauge) external view returns (int128);
+
+ function admin() external view returns (IAuthorizerAdaptor);
+
+ function gauge_exists(address gauge) external view returns (bool);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IL2GaugeCheckpointer.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IL2GaugeCheckpointer.sol
new file mode 100644
index 0000000..11023cb
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IL2GaugeCheckpointer.sol
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity ^0.7.0;
+
+import "./IGaugeAdder.sol";
+import "./IStakelessGauge.sol";
+
+/**
+ * @title L2 Gauge Checkpointer interface
+ * @notice Manages checkpoints for L2 gauges, allowing to perform mutiple checkpoints in a single call.
+ * @dev Supports Polygon, Arbitrum, Optimism, Gnosis and ZKSync stakeless root gauges. Gauges to be checkpointed need
+ * to be added to the controller beforehand.
+ */
+interface IL2GaugeCheckpointer {
+ /**
+ * @dev Emitted when a gauge is added to the checkpointer.
+ */
+ event GaugeAdded(IGaugeAdder.GaugeType indexed gaugeType, IStakelessGauge indexed gauge);
+
+ /**
+ * @dev Emitted when a gauge is removed from the checkpointer.
+ */
+ event GaugeRemoved(IGaugeAdder.GaugeType indexed gaugeType, IStakelessGauge indexed gauge);
+
+ /**
+ * @dev Adds an array of gauges from the given type.
+ * Gauges added will be considered when performing checkpoints.
+ * The gauges to add should meet the following preconditions:
+ * - They must have been created in a valid GaugeFactory, according to GaugeAdder#isGaugeFromValidFactory.
+ * - They must exist in the GaugeController, according to GaugeController#gauge_exists.
+ * - They must not be killed.
+ * - They must not have been previously added to the checkpointer.
+ * @param gaugeType - Type of the gauge.
+ * @param gauges - Gauges to add.
+ */
+ function addGauges(IGaugeAdder.GaugeType gaugeType, IStakelessGauge[] calldata gauges) external;
+
+ /**
+ * @dev Removes an array of gauges from the given type.
+ * Removed gauges will not be considered when performing checkpoints. To remove gauges:
+ * - They must be killed.
+ * - They must have been previously added to the checkpointer.
+ * @param gaugeType - Type of the gauge.
+ * @param gauges - Gauges to remove.
+ */
+ function removeGauges(IGaugeAdder.GaugeType gaugeType, IStakelessGauge[] calldata gauges) external;
+
+ /**
+ * @dev Returns true if the given gauge was added for the given type; false otherwise.
+ * @param gaugeType - Type of the gauge.
+ * @param gauge - Gauge to check.
+ */
+ function hasGauge(IGaugeAdder.GaugeType gaugeType, IStakelessGauge gauge) external view returns (bool);
+
+ /**
+ * @dev Returns the amount of added gauges for a given type.
+ * @param gaugeType - Type of the gauge.
+ */
+ function getTotalGauges(IGaugeAdder.GaugeType gaugeType) external view returns (uint256);
+
+ /**
+ * @dev Returns the gauge of a given type at the given index.
+ * Reverts if the index is greater than or equal to the amount of added gauges for the given type.
+ * @param gaugeType - Type of the gauge.
+ * @param index - Index of the added gauge.
+ */
+ function getGaugeAtIndex(IGaugeAdder.GaugeType gaugeType, uint256 index) external view returns (IStakelessGauge);
+
+ /**
+ * @dev Performs a checkpoint for all added gauges above the given relative weight threshold.
+ * Reverts if the ETH sent in the call is not enough to cover bridge costs.
+ * @param minRelativeWeight - Threshold to filter out gauges below it.
+ */
+ function checkpointGaugesAboveRelativeWeight(uint256 minRelativeWeight) external payable;
+
+ /**
+ * @dev Performs a checkpoint for all added gauges of a given type above the given relative weight threshold.
+ * Reverts if the ETH sent in the call is not enough to cover bridge costs.
+ * @param gaugeType - Type of the gauge.
+ * @param minRelativeWeight - Threshold to filter out gauges below it.
+ */
+ function checkpointGaugesOfTypeAboveRelativeWeight(IGaugeAdder.GaugeType gaugeType, uint256 minRelativeWeight)
+ external
+ payable;
+
+ /**
+ * @dev Returns the ETH cost to checkpoint all gauges for a given minimum relative weight.
+ * A lower minimum relative weight might return higher costs, since more gauges could potentially be included
+ * in the checkpoint.
+ */
+ function getTotalBridgeCost(uint256 minRelativeWeight) external view returns (uint256);
+
+ /**
+ * @dev Returns true if gauge type is Polygon, Arbitrum, Optimism, Gnosis or ZKSync; false otherwise.
+ */
+ function isSupportedGaugeType(IGaugeAdder.GaugeType gaugeType) external pure returns (bool);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILMGetters.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILMGetters.sol
new file mode 100644
index 0000000..de8505a
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILMGetters.sol
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "./IBalancerTokenAdmin.sol";
+import "./IGaugeController.sol";
+
+interface ILMGetters {
+ /**
+ * @notice Returns the address of the Balancer Token Admin contract
+ */
+ function getBalancerTokenAdmin() external view returns (IBalancerTokenAdmin);
+
+ /**
+ * @notice Returns the address of the Gauge Controller
+ */
+ function getGaugeController() external view returns (IGaugeController);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILiquidityGauge.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILiquidityGauge.sol
new file mode 100644
index 0000000..c6323ee
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILiquidityGauge.sol
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase
+// solhint-disable func-param-name-mixedcase
+
+interface ILiquidityGauge {
+ // solhint-disable-next-line var-name-mixedcase
+ event RelativeWeightCapChanged(uint256 new_relative_weight_cap);
+
+ /**
+ * @notice Returns BAL liquidity emissions calculated during checkpoints for the given user.
+ * @param user User address.
+ * @return uint256 BAL amount to issue for the address.
+ */
+ function integrate_fraction(address user) external view returns (uint256);
+
+ /**
+ * @notice Record a checkpoint for a given user.
+ * @param user User address.
+ * @return bool Always true.
+ */
+ function user_checkpoint(address user) external returns (bool);
+
+ /**
+ * @notice Returns true if gauge is killed; false otherwise.
+ */
+ function is_killed() external view returns (bool);
+
+ /**
+ * @notice Kills the gauge so it cannot mint BAL.
+ */
+ function killGauge() external;
+
+ /**
+ * @notice Unkills the gauge so it can mint BAL again.
+ */
+ function unkillGauge() external;
+
+ /**
+ * @notice Sets a new relative weight cap for the gauge.
+ * The value shall be normalized to 1e18, and not greater than MAX_RELATIVE_WEIGHT_CAP.
+ * @param relativeWeightCap New relative weight cap.
+ */
+ function setRelativeWeightCap(uint256 relativeWeightCap) external;
+
+ /**
+ * @notice Gets the relative weight cap for the gauge.
+ */
+ function getRelativeWeightCap() external view returns (uint256);
+
+ /**
+ * @notice Returns the gauge's relative weight for a given time, capped to its relative weight cap attribute.
+ * @param time Timestamp in the past or present.
+ */
+ function getCappedRelativeWeight(uint256 time) external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILiquidityGaugeFactory.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILiquidityGaugeFactory.sol
new file mode 100644
index 0000000..c7698e5
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ILiquidityGaugeFactory.sol
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "./ILiquidityGauge.sol";
+
+interface ILiquidityGaugeFactory {
+ /**
+ * @notice Returns true if `gauge` was created by this factory.
+ */
+ function isGaugeFromFactory(address gauge) external view returns (bool);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IMainnetBalancerMinter.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IMainnetBalancerMinter.sol
new file mode 100644
index 0000000..9f855a1
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IMainnetBalancerMinter.sol
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "./IBalancerMinter.sol";
+import "./ILMGetters.sol";
+
+/**
+ * @dev Full L1 Balancer minter interface with singleton getters.
+ */
+interface IMainnetBalancerMinter is IBalancerMinter, ILMGetters {
+ // solhint-disable-previous-line no-empty-blocks
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IOptimismGasLimitProvider.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IOptimismGasLimitProvider.sol
new file mode 100644
index 0000000..a165d93
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IOptimismGasLimitProvider.sol
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IOptimismGasLimitProvider {
+ function getOptimismGasLimit() external view returns (uint32 gasLimit);
+
+ function setOptimismGasLimit(uint32 gasLimit) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IRewardTokenDistributor.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IRewardTokenDistributor.sol
new file mode 100644
index 0000000..0b0ed3a
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IRewardTokenDistributor.sol
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase, var-name-mixedcase
+
+interface IRewardTokenDistributor {
+ struct Reward {
+ IERC20 token;
+ address distributor;
+ uint256 period_finish;
+ uint256 rate;
+ uint256 last_update;
+ uint256 integral;
+ }
+
+ function reward_tokens(uint256 index) external view returns (IERC20);
+
+ function reward_data(IERC20 token) external view returns (Reward memory);
+
+ function claim_rewards(address user) external;
+
+ function add_reward(IERC20 rewardToken, address distributor) external;
+
+ function set_reward_distributor(IERC20 rewardToken, address distributor) external;
+
+ function deposit_reward_token(IERC20 rewardToken, uint256 amount) external;
+
+ function claimable_reward(address rewardToken, address user) external view returns (uint256);
+
+ function claimable_reward_write(address rewardToken, address user) external returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IRewardsOnlyGauge.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IRewardsOnlyGauge.sol
new file mode 100644
index 0000000..0ff1cce
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IRewardsOnlyGauge.sol
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "./IChildChainStreamer.sol";
+import "./IRewardTokenDistributor.sol";
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase
+
+interface IRewardsOnlyGauge is IRewardTokenDistributor {
+ function initialize(
+ address pool,
+ address streamer,
+ bytes32 claimSignature
+ ) external;
+
+ // solhint-disable-next-line func-name-mixedcase
+ function lp_token() external view returns (IERC20);
+
+ function reward_contract() external view returns (IChildChainStreamer);
+
+ function set_rewards(
+ address childChainStreamer,
+ bytes32 claimSig,
+ address[8] calldata rewardTokens
+ ) external;
+
+ function last_claim() external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ISmartWalletChecker.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ISmartWalletChecker.sol
new file mode 100644
index 0000000..f7d6d8c
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/ISmartWalletChecker.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface ISmartWalletChecker {
+ function check(address contractAddress) external view returns (bool);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IStakelessGauge.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IStakelessGauge.sol
new file mode 100644
index 0000000..a63f126
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IStakelessGauge.sol
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "./ILiquidityGauge.sol";
+
+interface IStakelessGauge is ILiquidityGauge {
+ function checkpoint() external payable returns (bool);
+
+ function getRecipient() external view returns (address);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IStakingLiquidityGauge.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IStakingLiquidityGauge.sol
new file mode 100644
index 0000000..eb801e9
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IStakingLiquidityGauge.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+import "./ILiquidityGauge.sol";
+import "./IRewardTokenDistributor.sol";
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase, var-name-mixedcase
+
+interface IStakingLiquidityGauge is IRewardTokenDistributor, ILiquidityGauge, IERC20 {
+ function initialize(address lpToken, uint256 relativeWeightCap) external;
+
+ function lp_token() external view returns (IERC20);
+
+ function deposit(uint256 value, address recipient) external;
+
+ function withdraw(uint256 value) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IVeDelegation.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IVeDelegation.sol
new file mode 100644
index 0000000..8b9e40c
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IVeDelegation.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase
+
+interface IVeDelegation {
+ // solhint-disable-next-line func-name-mixedcase
+ function adjusted_balance_of(address user) external view returns (uint256);
+
+ function totalSupply() external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IVotingEscrow.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IVotingEscrow.sol
new file mode 100644
index 0000000..5a8ac65
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/liquidity-mining/IVotingEscrow.sol
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "./IAuthorizerAdaptor.sol";
+
+// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
+// naming convention.
+// solhint-disable func-name-mixedcase
+
+interface IVotingEscrow {
+ struct Point {
+ int128 bias;
+ int128 slope; // - dweight / dt
+ uint256 ts;
+ uint256 blk; // block
+ }
+
+ function epoch() external view returns (uint256);
+
+ function totalSupply(uint256 timestamp) external view returns (uint256);
+
+ function user_point_epoch(address user) external view returns (uint256);
+
+ function point_history(uint256 timestamp) external view returns (Point memory);
+
+ function user_point_history(address user, uint256 timestamp) external view returns (Point memory);
+
+ function checkpoint() external;
+
+ function admin() external view returns (IAuthorizerAdaptor);
+
+ function smart_wallet_checker() external view returns (address);
+
+ function commit_smart_wallet_checker(address newSmartWalletChecker) external;
+
+ function apply_smart_wallet_checker() external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-linear/IERC4626.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-linear/IERC4626.sol
new file mode 100644
index 0000000..107bc0d
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-linear/IERC4626.sol
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @title IERC4626, to support the yield-bearing token standard.
+ * @notice Used for ERC4626-derived Linear Pools.
+ * @dev There is another version of this in /solidity-utils/misc, used in standalone-utils tests.
+ * This version has an additional `previewMint` function, and is used in tests of derived Linear Pools.
+ */
+interface IERC4626 {
+ /**
+ * @dev Mints `shares` Vault shares to `receiver` by depositing exactly `amount` of underlying tokens.
+ */
+ function deposit(uint256 assets, address receiver) external returns (uint256 shares);
+
+ /**
+ * @dev Burns exactly `shares` from `owner` and sends `assets` of underlying tokens to `receiver`.
+ */
+ function redeem(
+ uint256 shares,
+ address receiver,
+ address owner
+ ) external returns (uint256 assets);
+
+ /**
+ * @dev The address of the underlying token that the Vault uses for accounting, depositing, and withdrawing.
+ */
+ function asset() external view returns (address);
+
+ /**
+ * @dev Total amount of the underlying asset that is “managed” by Vault.
+ */
+ function totalAssets() external view returns (uint256);
+
+ /**
+ * @dev The amount of `assets` that the Vault would exchange for the amount
+ * of `shares` provided, in an ideal scenario where all the conditions are met.
+ */
+ function convertToAssets(uint256 shares) external view returns (uint256 assets);
+
+ /**
+ * @dev The amount of `shares` that the Vault would exchange for the amount
+ * of `assets` provided, in an ideal scenario where all the conditions are met.
+ */
+ function convertToShares(uint256 assets) external view returns (uint256 shares);
+
+ /**
+ * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block,
+ * given current on-chain conditions. MUST return as close to and no fewer than the exact amount of assets that
+ * would be deposited in a mint call in the same transaction. I.e. mint should return the same or fewer assets
+ * as previewMint if called in the same transaction.
+ */
+ function previewMint(uint256 shares) external view returns (uint256 assets);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-linear/ILinearPool.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-linear/ILinearPool.sol
new file mode 100644
index 0000000..bc06538
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-linear/ILinearPool.sol
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+import "../vault/IBasePool.sol";
+
+interface ILinearPool is IBasePool {
+ /**
+ * @dev Returns the Pool's main token.
+ */
+ function getMainToken() external view returns (IERC20);
+
+ /**
+ * @dev Returns the Pool's wrapped token.
+ */
+ function getWrappedToken() external view returns (IERC20);
+
+ /**
+ * @dev Returns the index of the Pool's BPT in the Pool tokens array (as returned by IVault.getPoolTokens).
+ */
+ function getBptIndex() external view returns (uint256);
+
+ /**
+ * @dev Returns the index of the Pool's main token in the Pool tokens array (as returned by IVault.getPoolTokens).
+ */
+ function getMainIndex() external view returns (uint256);
+
+ /**
+ * @dev Returns the index of the Pool's wrapped token in the Pool tokens array (as returned by
+ * IVault.getPoolTokens).
+ */
+ function getWrappedIndex() external view returns (uint256);
+
+ /**
+ * @dev Returns the Pool's targets for the main token balance. These values have had the main token's scaling
+ * factor applied to them.
+ */
+ function getTargets() external view returns (uint256 lowerTarget, uint256 upperTarget);
+
+ /**
+ * @notice Set the lower and upper bounds of the zero-fee trading range for the main token balance.
+ * @dev For a new target range to be valid:
+ * - the current balance must be between the current targets (meaning no fees are currently pending)
+ * - the current balance must be between the new targets (meaning setting them does not create pending fees)
+ *
+ * The first requirement could be relaxed, as the LPs actually benefit from the pending fees not being paid out,
+ * but being stricter makes analysis easier at little expense.
+ *
+ * This is a permissioned function, reserved for the pool owner. It will revert when called within a Vault context
+ * (i.e. in the middle of a join or an exit).
+ *
+ * Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
+ * the pool during execution of a Vault hook.
+ *
+ * See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ */
+ function setTargets(uint256 newLowerTarget, uint256 newUpperTarget) external;
+
+ /**
+ * @notice Set the swap fee percentage.
+ * @dev This is a permissioned function, reserved for the pool owner. It will revert when called within a Vault
+ * context (i.e. in the middle of a join or an exit).
+ *
+ * Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
+ * the pool during execution of a Vault hook.
+ *
+ * See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ */
+ function setSwapFeePercentage(uint256 swapFeePercentage) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-stable/IComposableStablePoolRates.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-stable/IComposableStablePoolRates.sol
new file mode 100644
index 0000000..b1a5d30
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-stable/IComposableStablePoolRates.sol
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface IComposableStablePoolRates {
+ /**
+ * @dev Forces a rate cache hit for a token.
+ * It will revert if the requested token does not have an associated rate provider.
+ */
+ function updateTokenRateCache(IERC20 token) external;
+
+ /**
+ * @dev Sets a new duration for a token rate cache. It reverts if there was no rate provider set initially.
+ * Note this function also updates the current cached value.
+ * @param duration Number of seconds until the current token rate is fetched again.
+ */
+ function setTokenRateCacheDuration(IERC20 token, uint256 duration) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-stable/StablePoolUserData.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-stable/StablePoolUserData.sol
new file mode 100644
index 0000000..3c66a1f
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-stable/StablePoolUserData.sol
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+library StablePoolUserData {
+ enum JoinKind { INIT, EXACT_TOKENS_IN_FOR_BPT_OUT, TOKEN_IN_FOR_EXACT_BPT_OUT, ALL_TOKENS_IN_FOR_EXACT_BPT_OUT }
+ enum ExitKind { EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, BPT_IN_FOR_EXACT_TOKENS_OUT, EXACT_BPT_IN_FOR_ALL_TOKENS_OUT }
+
+ function joinKind(bytes memory self) internal pure returns (JoinKind) {
+ return abi.decode(self, (JoinKind));
+ }
+
+ function exitKind(bytes memory self) internal pure returns (ExitKind) {
+ return abi.decode(self, (ExitKind));
+ }
+
+ // Joins
+
+ function initialAmountsIn(bytes memory self) internal pure returns (uint256[] memory amountsIn) {
+ (, amountsIn) = abi.decode(self, (JoinKind, uint256[]));
+ }
+
+ function exactTokensInForBptOut(bytes memory self)
+ internal
+ pure
+ returns (uint256[] memory amountsIn, uint256 minBPTAmountOut)
+ {
+ (, amountsIn, minBPTAmountOut) = abi.decode(self, (JoinKind, uint256[], uint256));
+ }
+
+ function tokenInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut, uint256 tokenIndex) {
+ (, bptAmountOut, tokenIndex) = abi.decode(self, (JoinKind, uint256, uint256));
+ }
+
+ function allTokensInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut) {
+ (, bptAmountOut) = abi.decode(self, (JoinKind, uint256));
+ }
+
+ // Exits
+
+ function exactBptInForTokenOut(bytes memory self) internal pure returns (uint256 bptAmountIn, uint256 tokenIndex) {
+ (, bptAmountIn, tokenIndex) = abi.decode(self, (ExitKind, uint256, uint256));
+ }
+
+ function exactBptInForTokensOut(bytes memory self) internal pure returns (uint256 bptAmountIn) {
+ (, bptAmountIn) = abi.decode(self, (ExitKind, uint256));
+ }
+
+ function bptInForExactTokensOut(bytes memory self)
+ internal
+ pure
+ returns (uint256[] memory amountsOut, uint256 maxBPTAmountIn)
+ {
+ (, amountsOut, maxBPTAmountIn) = abi.decode(self, (ExitKind, uint256[], uint256));
+ }
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/BasePoolUserData.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/BasePoolUserData.sol
new file mode 100644
index 0000000..0703ac8
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/BasePoolUserData.sol
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+library BasePoolUserData {
+ // Special ExitKind for all pools, used in Recovery Mode. Use the max 8-bit value to prevent conflicts
+ // with future additions to the ExitKind enums (or any front-end code that maps to existing values)
+ uint8 public constant RECOVERY_MODE_EXIT_KIND = 255;
+
+ // Return true if this is the special exit kind.
+ function isRecoveryModeExitKind(bytes memory self) internal pure returns (bool) {
+ // Check for the "no data" case, or abi.decode would revert
+ return self.length > 0 && abi.decode(self, (uint8)) == RECOVERY_MODE_EXIT_KIND;
+ }
+
+ // Parse the bptAmountIn out of the userData
+ function recoveryModeExit(bytes memory self) internal pure returns (uint256 bptAmountIn) {
+ (, bptAmountIn) = abi.decode(self, (uint8, uint256));
+ }
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IBasePoolController.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IBasePoolController.sol
new file mode 100644
index 0000000..f752a82
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IBasePoolController.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IBasePoolController {
+ function initialize(address poolAddress) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IBasePoolFactory.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IBasePoolFactory.sol
new file mode 100644
index 0000000..694485f
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IBasePoolFactory.sol
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/helpers/IAuthentication.sol";
+
+interface IBasePoolFactory is IAuthentication {
+ /**
+ * @dev Returns true if `pool` was created by this factory.
+ */
+ function isPoolFromFactory(address pool) external view returns (bool);
+
+ /**
+ * @dev Check whether the derived factory has been disabled.
+ */
+ function isDisabled() external view returns (bool);
+
+ /**
+ * @dev Disable the factory, preventing the creation of more pools. Already existing pools are unaffected.
+ * Once a factory is disabled, it cannot be re-enabled.
+ */
+ function disable() external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IControlledPool.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IControlledPool.sol
new file mode 100644
index 0000000..a03d277
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IControlledPool.sol
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface IControlledPool {
+ function setSwapFeePercentage(uint256 swapFeePercentage) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IFactoryCreatedPoolVersion.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IFactoryCreatedPoolVersion.sol
new file mode 100644
index 0000000..62e4b24
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IFactoryCreatedPoolVersion.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @notice Simple interface to retrieve the version of pools deployed by a pool factory.
+ */
+interface IFactoryCreatedPoolVersion {
+ /**
+ * @dev Returns a JSON representation of the deployed pool version containing name, version number and task ID.
+ *
+ * This is typically only useful in complex Pool deployment schemes, where multiple subsystems need to know about
+ * each other. Note that this value will only be updated at factory creation time.
+ */
+ function getPoolVersion() external view returns (string memory);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/ILastCreatedPoolFactory.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/ILastCreatedPoolFactory.sol
new file mode 100644
index 0000000..2ac07ed
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/ILastCreatedPoolFactory.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "./IBasePoolFactory.sol";
+
+interface ILastCreatedPoolFactory is IBasePoolFactory {
+ /**
+ * @dev Returns the address of the last Pool created by this factory.
+ *
+ * This is typically only useful in complex Pool deployment schemes, where multiple subsystems need to know about
+ * each other. Note that this value will only be updated once construction of the last created Pool finishes.
+ */
+ function getLastCreatedPool() external view returns (address);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IManagedPool.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IManagedPool.sol
new file mode 100644
index 0000000..3094888
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IManagedPool.sol
@@ -0,0 +1,363 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+import "../vault/IBasePool.sol";
+
+interface IManagedPool is IBasePool {
+ event GradualSwapFeeUpdateScheduled(
+ uint256 startTime,
+ uint256 endTime,
+ uint256 startSwapFeePercentage,
+ uint256 endSwapFeePercentage
+ );
+ event GradualWeightUpdateScheduled(
+ uint256 startTime,
+ uint256 endTime,
+ uint256[] startWeights,
+ uint256[] endWeights
+ );
+ event SwapEnabledSet(bool swapEnabled);
+ event JoinExitEnabledSet(bool joinExitEnabled);
+ event MustAllowlistLPsSet(bool mustAllowlistLPs);
+ event AllowlistAddressAdded(address indexed member);
+ event AllowlistAddressRemoved(address indexed member);
+ event ManagementAumFeePercentageChanged(uint256 managementAumFeePercentage);
+ event ManagementAumFeeCollected(uint256 bptAmount);
+ event CircuitBreakerSet(
+ IERC20 indexed token,
+ uint256 bptPrice,
+ uint256 lowerBoundPercentage,
+ uint256 upperBoundPercentage
+ );
+ event TokenAdded(IERC20 indexed token, uint256 normalizedWeight);
+ event TokenRemoved(IERC20 indexed token);
+
+ /**
+ * @notice Returns the effective BPT supply.
+ *
+ * @dev The Pool owes debt to the Protocol and the Pool's owner in the form of unminted BPT, which will be minted
+ * immediately before the next join or exit. We need to take these into account since, even if they don't yet exist,
+ * they will effectively be included in any Pool operation that involves BPT.
+ *
+ * In the vast majority of cases, this function should be used instead of `totalSupply()`.
+ *
+ * WARNING: since this function reads balances directly from the Vault, it is potentially subject to manipulation
+ * via reentrancy. See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ *
+ * To call this function safely, attempt to trigger the reentrancy guard in the Vault by calling a non-reentrant
+ * function before calling `getActualSupply`. That will make the transaction revert in an unsafe context.
+ * (See `whenNotInVaultContext` in `ManagedPoolSettings`).
+ */
+ function getActualSupply() external view returns (uint256);
+
+ // Swap fee percentage
+
+ /**
+ * @notice Schedule a gradual swap fee update.
+ * @dev The swap fee will change from the given starting value (which may or may not be the current
+ * value) to the given ending fee percentage, over startTime to endTime.
+ *
+ * Note that calling this with a starting swap fee different from the current value will immediately change the
+ * current swap fee to `startSwapFeePercentage`, before commencing the gradual change at `startTime`.
+ * Emits the GradualSwapFeeUpdateScheduled event.
+ * This is a permissioned function.
+ *
+ * @param startTime - The timestamp when the swap fee change will begin.
+ * @param endTime - The timestamp when the swap fee change will end (must be >= startTime).
+ * @param startSwapFeePercentage - The starting value for the swap fee change.
+ * @param endSwapFeePercentage - The ending value for the swap fee change. If the current timestamp >= endTime,
+ * `getSwapFeePercentage()` will return this value.
+ */
+ function updateSwapFeeGradually(
+ uint256 startTime,
+ uint256 endTime,
+ uint256 startSwapFeePercentage,
+ uint256 endSwapFeePercentage
+ ) external;
+
+ /**
+ * @notice Returns the current gradual swap fee update parameters.
+ * @dev The current swap fee can be retrieved via `getSwapFeePercentage()`.
+ * @return startTime - The timestamp when the swap fee update will begin.
+ * @return endTime - The timestamp when the swap fee update will end.
+ * @return startSwapFeePercentage - The starting swap fee percentage (could be different from the current value).
+ * @return endSwapFeePercentage - The final swap fee percentage, when the current timestamp >= endTime.
+ */
+ function getGradualSwapFeeUpdateParams()
+ external
+ view
+ returns (
+ uint256 startTime,
+ uint256 endTime,
+ uint256 startSwapFeePercentage,
+ uint256 endSwapFeePercentage
+ );
+
+ // Token weights
+
+ /**
+ * @notice Schedule a gradual weight change.
+ * @dev The weights will change from their current values to the given endWeights, over startTime to endTime.
+ * This is a permissioned function.
+ *
+ * Since, unlike with swap fee updates, we generally do not want to allow instantaneous weight changes,
+ * the weights always start from their current values. This also guarantees a smooth transition when
+ * updateWeightsGradually is called during an ongoing weight change.
+ * @param startTime - The timestamp when the weight change will begin.
+ * @param endTime - The timestamp when the weight change will end (can be >= startTime).
+ * @param tokens - The tokens associated with the target weights (must match the current pool tokens).
+ * @param endWeights - The target weights. If the current timestamp >= endTime, `getNormalizedWeights()`
+ * will return these values.
+ */
+ function updateWeightsGradually(
+ uint256 startTime,
+ uint256 endTime,
+ IERC20[] memory tokens,
+ uint256[] memory endWeights
+ ) external;
+
+ /**
+ * @notice Returns all normalized weights, in the same order as the Pool's tokens.
+ */
+ function getNormalizedWeights() external view returns (uint256[] memory);
+
+ /**
+ * @notice Returns the current gradual weight change update parameters.
+ * @dev The current weights can be retrieved via `getNormalizedWeights()`.
+ * @return startTime - The timestamp when the weight update will begin.
+ * @return endTime - The timestamp when the weight update will end.
+ * @return startWeights - The starting weights, when the weight change was initiated.
+ * @return endWeights - The final weights, when the current timestamp >= endTime.
+ */
+ function getGradualWeightUpdateParams()
+ external
+ view
+ returns (
+ uint256 startTime,
+ uint256 endTime,
+ uint256[] memory startWeights,
+ uint256[] memory endWeights
+ );
+
+ // Join and Exit enable/disable
+
+ /**
+ * @notice Enable or disable joins and exits. Note that this does not affect Recovery Mode exits.
+ * @dev Emits the JoinExitEnabledSet event. This is a permissioned function.
+ * @param joinExitEnabled - The new value of the join/exit enabled flag.
+ */
+ function setJoinExitEnabled(bool joinExitEnabled) external;
+
+ /**
+ * @notice Returns whether joins and exits are enabled.
+ */
+ function getJoinExitEnabled() external view returns (bool);
+
+ // Swap enable/disable
+
+ /**
+ * @notice Enable or disable trading.
+ * @dev Emits the SwapEnabledSet event. This is a permissioned function.
+ * @param swapEnabled - The new value of the swap enabled flag.
+ */
+ function setSwapEnabled(bool swapEnabled) external;
+
+ /**
+ * @notice Returns whether swaps are enabled.
+ */
+ function getSwapEnabled() external view returns (bool);
+
+ // LP Allowlist
+
+ /**
+ * @notice Enable or disable the LP allowlist.
+ * @dev Note that any addresses added to the allowlist will be retained if the allowlist is toggled off and
+ * back on again, because this action does not affect the list of LP addresses.
+ * Emits the MustAllowlistLPsSet event. This is a permissioned function.
+ * @param mustAllowlistLPs - The new value of the mustAllowlistLPs flag.
+ */
+ function setMustAllowlistLPs(bool mustAllowlistLPs) external;
+
+ /**
+ * @notice Adds an address to the LP allowlist.
+ * @dev Will fail if the address is already allowlisted.
+ * Emits the AllowlistAddressAdded event. This is a permissioned function.
+ * @param member - The address to be added to the allowlist.
+ */
+ function addAllowedAddress(address member) external;
+
+ /**
+ * @notice Removes an address from the LP allowlist.
+ * @dev Will fail if the address was not previously allowlisted.
+ * Emits the AllowlistAddressRemoved event. This is a permissioned function.
+ * @param member - The address to be removed from the allowlist.
+ */
+ function removeAllowedAddress(address member) external;
+
+ /**
+ * @notice Returns whether the allowlist for LPs is enabled.
+ */
+ function getMustAllowlistLPs() external view returns (bool);
+
+ /**
+ * @notice Check whether an LP address is on the allowlist.
+ * @dev This simply checks the list, regardless of whether the allowlist feature is enabled.
+ * @param member - The address to check against the allowlist.
+ * @return true if the given address is on the allowlist.
+ */
+ function isAddressOnAllowlist(address member) external view returns (bool);
+
+ // Management fees
+
+ /**
+ * @notice Collect any accrued AUM fees and send them to the pool manager.
+ * @dev This can be called by anyone to collect accrued AUM fees - and will be called automatically
+ * whenever the supply changes (e.g., joins and exits, add and remove token), and before the fee
+ * percentage is changed by the manager, to prevent fees from being applied retroactively.
+ *
+ * Correct behavior depends on the current supply, which is potentially manipulable if the pool
+ * is reentered during execution of a Vault hook. This is protected where overridden in ManagedPoolSettings,
+ * and so is safe to call on ManagedPool.
+ *
+ * See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ *
+ * @return The amount of BPT minted to the manager.
+ */
+ function collectAumManagementFees() external returns (uint256);
+
+ /**
+ * @notice Setter for the yearly percentage AUM management fee, which is payable to the pool manager.
+ * @dev Attempting to collect AUM fees in excess of the maximum permitted percentage will revert.
+ * To avoid retroactive fee increases, we force collection at the current fee percentage before processing
+ * the update. Emits the ManagementAumFeePercentageChanged event. This is a permissioned function.
+ *
+ * To prevent changing management fees retroactively, this triggers payment of protocol fees before applying
+ * the change. Correct behavior depends on the current supply, which is potentially manipulable if the pool
+ * is reentered during execution of a Vault hook. This is protected where overridden in ManagedPoolSettings,
+ * and so is safe to call on ManagedPool.
+ *
+ * See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ *
+ * @param managementAumFeePercentage - The new management AUM fee percentage.
+ * @return amount - The amount of BPT minted to the manager before the update, if any.
+ */
+ function setManagementAumFeePercentage(uint256 managementAumFeePercentage) external returns (uint256);
+
+ /**
+ * @notice Returns the management AUM fee percentage as an 18-decimal fixed point number and the timestamp of the
+ * last collection of AUM fees.
+ */
+ function getManagementAumFeeParams()
+ external
+ view
+ returns (uint256 aumFeePercentage, uint256 lastCollectionTimestamp);
+
+ // Circuit Breakers
+
+ /**
+ * @notice Set a circuit breaker for one or more tokens.
+ * @dev This is a permissioned function. The lower and upper bounds are percentages, corresponding to a
+ * relative change in the token's spot price: e.g., a lower bound of 0.8 means the breaker should prevent
+ * trades that result in the value of the token dropping 20% or more relative to the rest of the pool.
+ */
+ function setCircuitBreakers(
+ IERC20[] memory tokens,
+ uint256[] memory bptPrices,
+ uint256[] memory lowerBoundPercentages,
+ uint256[] memory upperBoundPercentages
+ ) external;
+
+ /**
+ * @notice Return the full circuit breaker state for the given token.
+ * @dev These are the reference values (BPT price and reference weight) passed in when the breaker was set,
+ * along with the percentage bounds. It also returns the current BPT price bounds, needed to check whether
+ * the circuit breaker should trip.
+ */
+ function getCircuitBreakerState(IERC20 token)
+ external
+ view
+ returns (
+ uint256 bptPrice,
+ uint256 referenceWeight,
+ uint256 lowerBound,
+ uint256 upperBound,
+ uint256 lowerBptPriceBound,
+ uint256 upperBptPriceBound
+ );
+
+ // Add/remove tokens
+
+ /**
+ * @notice Adds a token to the Pool's list of tradeable tokens. This is a permissioned function.
+ *
+ * @dev By adding a token to the Pool's composition, the weights of all other tokens will be decreased. The new
+ * token will have no balance - it is up to the owner to provide some immediately after calling this function.
+ * Note however that regular join functions will not work while the new token has no balance: the only way to
+ * deposit an initial amount is by using an Asset Manager.
+ *
+ * Token addition is forbidden during a weight change, or if one is scheduled to happen in the future.
+ *
+ * The caller may additionally pass a non-zero `mintAmount` to have some BPT be minted for them, which might be
+ * useful in some scenarios to account for the fact that the Pool will have more tokens.
+ *
+ * Emits the TokenAdded event. This is a permissioned function.
+ *
+ * Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
+ * the pool during execution of a Vault hook. This is protected where overridden in ManagedPoolSettings,
+ * and so is safe to call on ManagedPool.
+ *
+ * See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ *
+ * @param tokenToAdd - The ERC20 token to be added to the Pool.
+ * @param assetManager - The Asset Manager for the token.
+ * @param tokenToAddNormalizedWeight - The normalized weight of `token` relative to the other tokens in the Pool.
+ * @param mintAmount - The amount of BPT to be minted as a result of adding `token` to the Pool.
+ * @param recipient - The address to receive the BPT minted by the Pool.
+ */
+ function addToken(
+ IERC20 tokenToAdd,
+ address assetManager,
+ uint256 tokenToAddNormalizedWeight,
+ uint256 mintAmount,
+ address recipient
+ ) external;
+
+ /**
+ * @notice Removes a token from the Pool's list of tradeable tokens.
+ * @dev Tokens can only be removed if the Pool has more than 2 tokens, as it can never have fewer than 2 (not
+ * including BPT). Token removal is also forbidden during a weight change, or if one is scheduled to happen in
+ * the future.
+ *
+ * Emits the TokenRemoved event. This is a permissioned function.
+ * Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
+ * the pool during execution of a Vault hook. This is protected where overridden in ManagedPoolSettings,
+ * and so is safe to call on ManagedPool.
+ *
+ * See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ *
+ * The caller may additionally pass a non-zero `burnAmount` to burn some of their BPT, which might be useful
+ * in some scenarios to account for the fact that the Pool now has fewer tokens. This is a permissioned function.
+ * @param tokenToRemove - The ERC20 token to be removed from the Pool.
+ * @param burnAmount - The amount of BPT to be burned after removing `token` from the Pool.
+ * @param sender - The address to burn BPT from.
+ */
+ function removeToken(
+ IERC20 tokenToRemove,
+ uint256 burnAmount,
+ address sender
+ ) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IPoolVersion.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IPoolVersion.sol
new file mode 100644
index 0000000..56d3e4c
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IPoolVersion.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @notice Simple interface to retrieve the version of pools deployed by a pool factory.
+ */
+interface IPoolVersion {
+ /**
+ * @dev Returns a JSON representation of the deployed pool version containing name, version number and task ID.
+ *
+ * This is typically only useful in complex Pool deployment schemes, where multiple subsystems need to know about
+ * each other. Note that this value will only be updated at factory creation time.
+ */
+ function getPoolVersion() external view returns (string memory);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IProtocolFeeCache.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IProtocolFeeCache.sol
new file mode 100644
index 0000000..887c840
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IProtocolFeeCache.sol
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IProtocolFeeCache {
+ /**
+ * @notice Updates the cache to the latest value set by governance.
+ * @dev Can be called by anyone to update the cached fee percentages.
+ *
+ * Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
+ * the pool during execution of a Vault hook. This is protected by a call to `ensureNotInVaultContext` in
+ * VaultReentrancyLib where overridden in `ProtocolFeeCache`, and so is safe to call on ManagedPool.
+ *
+ * See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ */
+ function updateProtocolFeePercentageCache() external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRateProvider.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRateProvider.sol
new file mode 100644
index 0000000..86ba490
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRateProvider.sol
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IRateProvider {
+ /**
+ * @dev Returns an 18 decimal fixed point number that is the exchange rate of the token to some other underlying
+ * token. The meaning of this rate depends on the context.
+ */
+ function getRate() external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRateProviderPool.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRateProviderPool.sol
new file mode 100644
index 0000000..c2c6124
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRateProviderPool.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "./IRateProvider.sol";
+
+/**
+ * @dev Interface for Pools that assign rate providers to their tokens.
+ */
+interface IRateProviderPool {
+ /**
+ * @dev Returns the rate provider for each of the Pool's tokens. A zero-address entry means there's no rate provider
+ * for that token.
+ */
+ function getRateProviders() external view returns (IRateProvider[] memory);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRecoveryMode.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRecoveryMode.sol
new file mode 100644
index 0000000..9590de2
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRecoveryMode.sol
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev Interface for the RecoveryMode module.
+ */
+interface IRecoveryMode {
+ /**
+ * @dev Emitted when the Recovery Mode status changes.
+ */
+ event RecoveryModeStateChanged(bool enabled);
+
+ /**
+ * @notice Enables Recovery Mode in the Pool, disabling protocol fee collection and allowing for safe proportional
+ * exits with low computational complexity and no dependencies.
+ */
+ function enableRecoveryMode() external;
+
+ /**
+ * @notice Disables Recovery Mode in the Pool, restoring protocol fee collection and disallowing proportional exits.
+ */
+ function disableRecoveryMode() external;
+
+ /**
+ * @notice Returns true if the Pool is in Recovery Mode.
+ */
+ function inRecoveryMode() external view returns (bool);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRecoveryModeHelper.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRecoveryModeHelper.sol
new file mode 100644
index 0000000..b948f13
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IRecoveryModeHelper.sol
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../vault/IVault.sol";
+
+/**
+ * Interface for an auxiliary contract that computes Recovery Mode exits, removing logic from the core Pool contract
+ * that would otherwise take up a lot of bytecode size at the cost of some slight gas overhead. Since Recovery Mode
+ * exits are expected to be highly infrequent (and ideally never occur), this tradeoff makes sense.
+ */
+interface IRecoveryModeHelper {
+ /**
+ * @notice Returns the Balancer Vault
+ */
+ function getVault() external view returns (IVault);
+
+ /**
+ * @dev Computes a Recovery Mode Exit BPT and token amounts for a Pool. Only 'cash' balances are considered, to
+ * avoid scenarios where the last LPs to attempt to exit the Pool cannot do it because only 'managed' balance
+ * remains.
+ *
+ * The Pool is assumed to be a Composable Pool that uses ComposablePoolLib, meaning BPT will be its first token. It
+ * is also assumed that there is no 'managed' balance for BPT.
+
+ * WARNING: since this function reads balances directly from the Vault, it is potentially subject to manipulation
+ * via reentrancy. See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
+ *
+ * To call this function safely, attempt to trigger the reentrancy guard in the Vault by calling a non-reentrant
+ * function before calling `calcComposableRecoveryAmountsOut`. That will make the transaction revert in an unsafe
+ * context.
+ *
+ * (See `VaultReentrancyLib.ensureNotInVaultContext`).
+ */
+ function calcComposableRecoveryAmountsOut(
+ bytes32 poolId,
+ bytes memory userData,
+ uint256 totalSupply
+ ) external view returns (uint256 bptAmountIn, uint256[] memory amountsOut);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IVersion.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IVersion.sol
new file mode 100644
index 0000000..9079808
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-utils/IVersion.sol
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @notice Simple interface to retrieve the version of a deployed contract.
+ */
+interface IVersion {
+ /**
+ * @dev Returns a JSON representation of the contract version containing name, version number and task ID.
+ */
+ function version() external view returns (string memory);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-weighted/IExternalWeightedMath.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-weighted/IExternalWeightedMath.sol
new file mode 100644
index 0000000..f26b3ea
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-weighted/IExternalWeightedMath.sol
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @notice Interface for ExternalWeightedMath, a contract-wrapper for Weighted Math, Joins and Exits.
+ */
+interface IExternalWeightedMath {
+ /**
+ * @dev See `WeightedMath._calculateInvariant`.
+ */
+ function calculateInvariant(uint256[] memory normalizedWeights, uint256[] memory balances)
+ external
+ pure
+ returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcOutGivenIn`.
+ */
+ function calcOutGivenIn(
+ uint256 balanceIn,
+ uint256 weightIn,
+ uint256 balanceOut,
+ uint256 weightOut,
+ uint256 amountIn
+ ) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcInGivenOut`.
+ */
+ function calcInGivenOut(
+ uint256 balanceIn,
+ uint256 weightIn,
+ uint256 balanceOut,
+ uint256 weightOut,
+ uint256 amountOut
+ ) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcBptOutGivenExactTokensIn`.
+ */
+ function calcBptOutGivenExactTokensIn(
+ uint256[] memory balances,
+ uint256[] memory normalizedWeights,
+ uint256[] memory amountsIn,
+ uint256 bptTotalSupply,
+ uint256 swapFeePercentage
+ ) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcBptOutGivenExactTokenIn`.
+ */
+ function calcBptOutGivenExactTokenIn(
+ uint256 balance,
+ uint256 normalizedWeight,
+ uint256 amountIn,
+ uint256 bptTotalSupply,
+ uint256 swapFeePercentage
+ ) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcTokenInGivenExactBptOut`.
+ */
+ function calcTokenInGivenExactBptOut(
+ uint256 balance,
+ uint256 normalizedWeight,
+ uint256 bptAmountOut,
+ uint256 bptTotalSupply,
+ uint256 swapFeePercentage
+ ) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcAllTokensInGivenExactBptOut`.
+ */
+ function calcAllTokensInGivenExactBptOut(
+ uint256[] memory balances,
+ uint256 bptAmountOut,
+ uint256 totalBPT
+ ) external pure returns (uint256[] memory);
+
+ /**
+ * @dev See `WeightedMath._calcBptInGivenExactTokensOut`.
+ */
+ function calcBptInGivenExactTokensOut(
+ uint256[] memory balances,
+ uint256[] memory normalizedWeights,
+ uint256[] memory amountsOut,
+ uint256 bptTotalSupply,
+ uint256 swapFeePercentage
+ ) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcBptInGivenExactTokenOut`.
+ */
+ function calcBptInGivenExactTokenOut(
+ uint256 balance,
+ uint256 normalizedWeight,
+ uint256 amountOut,
+ uint256 bptTotalSupply,
+ uint256 swapFeePercentage
+ ) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcTokenOutGivenExactBptIn`.
+ */
+ function calcTokenOutGivenExactBptIn(
+ uint256 balance,
+ uint256 normalizedWeight,
+ uint256 bptAmountIn,
+ uint256 bptTotalSupply,
+ uint256 swapFeePercentage
+ ) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedMath._calcTokensOutGivenExactBptIn`.
+ */
+ function calcTokensOutGivenExactBptIn(
+ uint256[] memory balances,
+ uint256 bptAmountIn,
+ uint256 totalBPT
+ ) external pure returns (uint256[] memory);
+
+ /**
+ * @dev See `WeightedMath._calcBptOutAddToken`.
+ */
+ function calcBptOutAddToken(uint256 totalSupply, uint256 normalizedWeight) external pure returns (uint256);
+
+ /**
+ * @dev See `WeightedJoinsLib.joinExactTokensInForBPTOut`.
+ */
+ function joinExactTokensInForBPTOut(
+ uint256[] memory balances,
+ uint256[] memory normalizedWeights,
+ uint256[] memory scalingFactors,
+ uint256 totalSupply,
+ uint256 swapFeePercentage,
+ bytes memory userData
+ ) external pure returns (uint256, uint256[] memory);
+
+ /**
+ * @dev See `WeightedJoinsLib.joinTokenInForExactBPTOut`.
+ */
+ function joinTokenInForExactBPTOut(
+ uint256[] memory balances,
+ uint256[] memory normalizedWeights,
+ uint256 totalSupply,
+ uint256 swapFeePercentage,
+ bytes memory userData
+ ) external pure returns (uint256, uint256[] memory);
+
+ /**
+ * @dev See `WeightedJoinsLib.joinAllTokensInForExactBPTOut`.
+ */
+ function joinAllTokensInForExactBPTOut(
+ uint256[] memory balances,
+ uint256 totalSupply,
+ bytes memory userData
+ ) external pure returns (uint256 bptAmountOut, uint256[] memory amountsIn);
+
+ /**
+ * @dev See `WeightedExitsLib.exitExactBPTInForTokenOut`.
+ */
+ function exitExactBPTInForTokenOut(
+ uint256[] memory balances,
+ uint256[] memory normalizedWeights,
+ uint256 totalSupply,
+ uint256 swapFeePercentage,
+ bytes memory userData
+ ) external pure returns (uint256, uint256[] memory);
+
+ /**
+ * @dev See `WeightedExitsLib.exitExactBPTInForTokensOut`.
+ */
+ function exitExactBPTInForTokensOut(
+ uint256[] memory balances,
+ uint256 totalSupply,
+ bytes memory userData
+ ) external pure returns (uint256 bptAmountIn, uint256[] memory amountsOut);
+
+ /**
+ * @dev See `WeightedExitsLib.exitBPTInForExactTokensOut`.
+ */
+ function exitBPTInForExactTokensOut(
+ uint256[] memory balances,
+ uint256[] memory normalizedWeights,
+ uint256[] memory scalingFactors,
+ uint256 totalSupply,
+ uint256 swapFeePercentage,
+ bytes memory userData
+ ) external pure returns (uint256, uint256[] memory);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-weighted/WeightedPoolUserData.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-weighted/WeightedPoolUserData.sol
new file mode 100644
index 0000000..e192e5a
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/pool-weighted/WeightedPoolUserData.sol
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+library WeightedPoolUserData {
+ // In order to preserve backwards compatibility, make sure new join and exit kinds are added at the end of the enum.
+ enum JoinKind { INIT, EXACT_TOKENS_IN_FOR_BPT_OUT, TOKEN_IN_FOR_EXACT_BPT_OUT, ALL_TOKENS_IN_FOR_EXACT_BPT_OUT }
+ enum ExitKind { EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, EXACT_BPT_IN_FOR_TOKENS_OUT, BPT_IN_FOR_EXACT_TOKENS_OUT }
+
+ function joinKind(bytes memory self) internal pure returns (JoinKind) {
+ return abi.decode(self, (JoinKind));
+ }
+
+ function exitKind(bytes memory self) internal pure returns (ExitKind) {
+ return abi.decode(self, (ExitKind));
+ }
+
+ // Joins
+
+ function initialAmountsIn(bytes memory self) internal pure returns (uint256[] memory amountsIn) {
+ (, amountsIn) = abi.decode(self, (JoinKind, uint256[]));
+ }
+
+ function exactTokensInForBptOut(bytes memory self)
+ internal
+ pure
+ returns (uint256[] memory amountsIn, uint256 minBPTAmountOut)
+ {
+ (, amountsIn, minBPTAmountOut) = abi.decode(self, (JoinKind, uint256[], uint256));
+ }
+
+ function tokenInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut, uint256 tokenIndex) {
+ (, bptAmountOut, tokenIndex) = abi.decode(self, (JoinKind, uint256, uint256));
+ }
+
+ function allTokensInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut) {
+ (, bptAmountOut) = abi.decode(self, (JoinKind, uint256));
+ }
+
+ // Exits
+
+ function exactBptInForTokenOut(bytes memory self) internal pure returns (uint256 bptAmountIn, uint256 tokenIndex) {
+ (, bptAmountIn, tokenIndex) = abi.decode(self, (ExitKind, uint256, uint256));
+ }
+
+ function exactBptInForTokensOut(bytes memory self) internal pure returns (uint256 bptAmountIn) {
+ (, bptAmountIn) = abi.decode(self, (ExitKind, uint256));
+ }
+
+ function bptInForExactTokensOut(bytes memory self)
+ internal
+ pure
+ returns (uint256[] memory amountsOut, uint256 maxBPTAmountIn)
+ {
+ (, amountsOut, maxBPTAmountIn) = abi.decode(self, (ExitKind, uint256[], uint256));
+ }
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/BalancerErrors.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/BalancerErrors.sol
new file mode 100644
index 0000000..f9bf4b6
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/BalancerErrors.sol
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+// solhint-disable
+
+/**
+ * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are
+ * supported.
+ * Uses the default 'BAL' prefix for the error code
+ */
+function _require(bool condition, uint256 errorCode) pure {
+ if (!condition) _revert(errorCode);
+}
+
+/**
+ * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are
+ * supported.
+ */
+function _require(
+ bool condition,
+ uint256 errorCode,
+ bytes3 prefix
+) pure {
+ if (!condition) _revert(errorCode, prefix);
+}
+
+/**
+ * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported.
+ * Uses the default 'BAL' prefix for the error code
+ */
+function _revert(uint256 errorCode) pure {
+ _revert(errorCode, 0x42414c); // This is the raw byte representation of "BAL"
+}
+
+/**
+ * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported.
+ */
+function _revert(uint256 errorCode, bytes3 prefix) pure {
+ uint256 prefixUint = uint256(uint24(prefix));
+ // We're going to dynamically create a revert string based on the error code, with the following format:
+ // 'BAL#{errorCode}'
+ // where the code is left-padded with zeroes to three digits (so they range from 000 to 999).
+ //
+ // We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a
+ // number (8 to 16 bits) than the individual string characters.
+ //
+ // The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a
+ // much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a
+ // safe place to rely on it without worrying about how its usage might affect e.g. memory contents.
+ assembly {
+ // First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999
+ // range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for
+ // the '0' character.
+
+ let units := add(mod(errorCode, 10), 0x30)
+
+ errorCode := div(errorCode, 10)
+ let tenths := add(mod(errorCode, 10), 0x30)
+
+ errorCode := div(errorCode, 10)
+ let hundreds := add(mod(errorCode, 10), 0x30)
+
+ // With the individual characters, we can now construct the full string.
+ // We first append the '#' character (0x23) to the prefix. In the case of 'BAL', it results in 0x42414c23 ('BAL#')
+ // Then, we shift this by 24 (to provide space for the 3 bytes of the error code), and add the
+ // characters to it, each shifted by a multiple of 8.
+ // The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits
+ // per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte
+ // array).
+ let formattedPrefix := shl(24, add(0x23, shl(8, prefixUint)))
+
+ let revertReason := shl(200, add(formattedPrefix, add(add(units, shl(8, tenths)), shl(16, hundreds))))
+
+ // We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded
+ // message will have the following layout:
+ // [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ]
+
+ // The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We
+ // also write zeroes to the next 28 bytes of memory, but those are about to be overwritten.
+ mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
+ // Next is the offset to the location of the string, which will be placed immediately after (20 bytes away).
+ mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
+ // The string length is fixed: 7 characters.
+ mstore(0x24, 7)
+ // Finally, the string itself is stored.
+ mstore(0x44, revertReason)
+
+ // Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of
+ // the encoded message is therefore 4 + 32 + 32 + 32 = 100.
+ revert(0, 100)
+ }
+}
+
+library Errors {
+ // Math
+ uint256 internal constant ADD_OVERFLOW = 0;
+ uint256 internal constant SUB_OVERFLOW = 1;
+ uint256 internal constant SUB_UNDERFLOW = 2;
+ uint256 internal constant MUL_OVERFLOW = 3;
+ uint256 internal constant ZERO_DIVISION = 4;
+ uint256 internal constant DIV_INTERNAL = 5;
+ uint256 internal constant X_OUT_OF_BOUNDS = 6;
+ uint256 internal constant Y_OUT_OF_BOUNDS = 7;
+ uint256 internal constant PRODUCT_OUT_OF_BOUNDS = 8;
+ uint256 internal constant INVALID_EXPONENT = 9;
+
+ // Input
+ uint256 internal constant OUT_OF_BOUNDS = 100;
+ uint256 internal constant UNSORTED_ARRAY = 101;
+ uint256 internal constant UNSORTED_TOKENS = 102;
+ uint256 internal constant INPUT_LENGTH_MISMATCH = 103;
+ uint256 internal constant ZERO_TOKEN = 104;
+ uint256 internal constant INSUFFICIENT_DATA = 105;
+
+ // Shared pools
+ uint256 internal constant MIN_TOKENS = 200;
+ uint256 internal constant MAX_TOKENS = 201;
+ uint256 internal constant MAX_SWAP_FEE_PERCENTAGE = 202;
+ uint256 internal constant MIN_SWAP_FEE_PERCENTAGE = 203;
+ uint256 internal constant MINIMUM_BPT = 204;
+ uint256 internal constant CALLER_NOT_VAULT = 205;
+ uint256 internal constant UNINITIALIZED = 206;
+ uint256 internal constant BPT_IN_MAX_AMOUNT = 207;
+ uint256 internal constant BPT_OUT_MIN_AMOUNT = 208;
+ uint256 internal constant EXPIRED_PERMIT = 209;
+ uint256 internal constant NOT_TWO_TOKENS = 210;
+ uint256 internal constant DISABLED = 211;
+
+ // Pools
+ uint256 internal constant MIN_AMP = 300;
+ uint256 internal constant MAX_AMP = 301;
+ uint256 internal constant MIN_WEIGHT = 302;
+ uint256 internal constant MAX_STABLE_TOKENS = 303;
+ uint256 internal constant MAX_IN_RATIO = 304;
+ uint256 internal constant MAX_OUT_RATIO = 305;
+ uint256 internal constant MIN_BPT_IN_FOR_TOKEN_OUT = 306;
+ uint256 internal constant MAX_OUT_BPT_FOR_TOKEN_IN = 307;
+ uint256 internal constant NORMALIZED_WEIGHT_INVARIANT = 308;
+ uint256 internal constant INVALID_TOKEN = 309;
+ uint256 internal constant UNHANDLED_JOIN_KIND = 310;
+ uint256 internal constant ZERO_INVARIANT = 311;
+ uint256 internal constant ORACLE_INVALID_SECONDS_QUERY = 312;
+ uint256 internal constant ORACLE_NOT_INITIALIZED = 313;
+ uint256 internal constant ORACLE_QUERY_TOO_OLD = 314;
+ uint256 internal constant ORACLE_INVALID_INDEX = 315;
+ uint256 internal constant ORACLE_BAD_SECS = 316;
+ uint256 internal constant AMP_END_TIME_TOO_CLOSE = 317;
+ uint256 internal constant AMP_ONGOING_UPDATE = 318;
+ uint256 internal constant AMP_RATE_TOO_HIGH = 319;
+ uint256 internal constant AMP_NO_ONGOING_UPDATE = 320;
+ uint256 internal constant STABLE_INVARIANT_DIDNT_CONVERGE = 321;
+ uint256 internal constant STABLE_GET_BALANCE_DIDNT_CONVERGE = 322;
+ uint256 internal constant RELAYER_NOT_CONTRACT = 323;
+ uint256 internal constant BASE_POOL_RELAYER_NOT_CALLED = 324;
+ uint256 internal constant REBALANCING_RELAYER_REENTERED = 325;
+ uint256 internal constant GRADUAL_UPDATE_TIME_TRAVEL = 326;
+ uint256 internal constant SWAPS_DISABLED = 327;
+ uint256 internal constant CALLER_IS_NOT_LBP_OWNER = 328;
+ uint256 internal constant PRICE_RATE_OVERFLOW = 329;
+ uint256 internal constant INVALID_JOIN_EXIT_KIND_WHILE_SWAPS_DISABLED = 330;
+ uint256 internal constant WEIGHT_CHANGE_TOO_FAST = 331;
+ uint256 internal constant LOWER_GREATER_THAN_UPPER_TARGET = 332;
+ uint256 internal constant UPPER_TARGET_TOO_HIGH = 333;
+ uint256 internal constant UNHANDLED_BY_LINEAR_POOL = 334;
+ uint256 internal constant OUT_OF_TARGET_RANGE = 335;
+ uint256 internal constant UNHANDLED_EXIT_KIND = 336;
+ uint256 internal constant UNAUTHORIZED_EXIT = 337;
+ uint256 internal constant MAX_MANAGEMENT_SWAP_FEE_PERCENTAGE = 338;
+ uint256 internal constant UNHANDLED_BY_MANAGED_POOL = 339;
+ uint256 internal constant UNHANDLED_BY_PHANTOM_POOL = 340;
+ uint256 internal constant TOKEN_DOES_NOT_HAVE_RATE_PROVIDER = 341;
+ uint256 internal constant INVALID_INITIALIZATION = 342;
+ uint256 internal constant OUT_OF_NEW_TARGET_RANGE = 343;
+ uint256 internal constant FEATURE_DISABLED = 344;
+ uint256 internal constant UNINITIALIZED_POOL_CONTROLLER = 345;
+ uint256 internal constant SET_SWAP_FEE_DURING_FEE_CHANGE = 346;
+ uint256 internal constant SET_SWAP_FEE_PENDING_FEE_CHANGE = 347;
+ uint256 internal constant CHANGE_TOKENS_DURING_WEIGHT_CHANGE = 348;
+ uint256 internal constant CHANGE_TOKENS_PENDING_WEIGHT_CHANGE = 349;
+ uint256 internal constant MAX_WEIGHT = 350;
+ uint256 internal constant UNAUTHORIZED_JOIN = 351;
+ uint256 internal constant MAX_MANAGEMENT_AUM_FEE_PERCENTAGE = 352;
+ uint256 internal constant FRACTIONAL_TARGET = 353;
+ uint256 internal constant ADD_OR_REMOVE_BPT = 354;
+ uint256 internal constant INVALID_CIRCUIT_BREAKER_BOUNDS = 355;
+ uint256 internal constant CIRCUIT_BREAKER_TRIPPED = 356;
+ uint256 internal constant MALICIOUS_QUERY_REVERT = 357;
+ uint256 internal constant JOINS_EXITS_DISABLED = 358;
+
+ // Lib
+ uint256 internal constant REENTRANCY = 400;
+ uint256 internal constant SENDER_NOT_ALLOWED = 401;
+ uint256 internal constant PAUSED = 402;
+ uint256 internal constant PAUSE_WINDOW_EXPIRED = 403;
+ uint256 internal constant MAX_PAUSE_WINDOW_DURATION = 404;
+ uint256 internal constant MAX_BUFFER_PERIOD_DURATION = 405;
+ uint256 internal constant INSUFFICIENT_BALANCE = 406;
+ uint256 internal constant INSUFFICIENT_ALLOWANCE = 407;
+ uint256 internal constant ERC20_TRANSFER_FROM_ZERO_ADDRESS = 408;
+ uint256 internal constant ERC20_TRANSFER_TO_ZERO_ADDRESS = 409;
+ uint256 internal constant ERC20_MINT_TO_ZERO_ADDRESS = 410;
+ uint256 internal constant ERC20_BURN_FROM_ZERO_ADDRESS = 411;
+ uint256 internal constant ERC20_APPROVE_FROM_ZERO_ADDRESS = 412;
+ uint256 internal constant ERC20_APPROVE_TO_ZERO_ADDRESS = 413;
+ uint256 internal constant ERC20_TRANSFER_EXCEEDS_ALLOWANCE = 414;
+ uint256 internal constant ERC20_DECREASED_ALLOWANCE_BELOW_ZERO = 415;
+ uint256 internal constant ERC20_TRANSFER_EXCEEDS_BALANCE = 416;
+ uint256 internal constant ERC20_BURN_EXCEEDS_ALLOWANCE = 417;
+ uint256 internal constant SAFE_ERC20_CALL_FAILED = 418;
+ uint256 internal constant ADDRESS_INSUFFICIENT_BALANCE = 419;
+ uint256 internal constant ADDRESS_CANNOT_SEND_VALUE = 420;
+ uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_INT256 = 421;
+ uint256 internal constant GRANT_SENDER_NOT_ADMIN = 422;
+ uint256 internal constant REVOKE_SENDER_NOT_ADMIN = 423;
+ uint256 internal constant RENOUNCE_SENDER_NOT_ALLOWED = 424;
+ uint256 internal constant BUFFER_PERIOD_EXPIRED = 425;
+ uint256 internal constant CALLER_IS_NOT_OWNER = 426;
+ uint256 internal constant NEW_OWNER_IS_ZERO = 427;
+ uint256 internal constant CODE_DEPLOYMENT_FAILED = 428;
+ uint256 internal constant CALL_TO_NON_CONTRACT = 429;
+ uint256 internal constant LOW_LEVEL_CALL_FAILED = 430;
+ uint256 internal constant NOT_PAUSED = 431;
+ uint256 internal constant ADDRESS_ALREADY_ALLOWLISTED = 432;
+ uint256 internal constant ADDRESS_NOT_ALLOWLISTED = 433;
+ uint256 internal constant ERC20_BURN_EXCEEDS_BALANCE = 434;
+ uint256 internal constant INVALID_OPERATION = 435;
+ uint256 internal constant CODEC_OVERFLOW = 436;
+ uint256 internal constant IN_RECOVERY_MODE = 437;
+ uint256 internal constant NOT_IN_RECOVERY_MODE = 438;
+ uint256 internal constant INDUCED_FAILURE = 439;
+ uint256 internal constant EXPIRED_SIGNATURE = 440;
+ uint256 internal constant MALFORMED_SIGNATURE = 441;
+ uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_UINT64 = 442;
+ uint256 internal constant UNHANDLED_FEE_TYPE = 443;
+ uint256 internal constant BURN_FROM_ZERO = 444;
+
+ // Vault
+ uint256 internal constant INVALID_POOL_ID = 500;
+ uint256 internal constant CALLER_NOT_POOL = 501;
+ uint256 internal constant SENDER_NOT_ASSET_MANAGER = 502;
+ uint256 internal constant USER_DOESNT_ALLOW_RELAYER = 503;
+ uint256 internal constant INVALID_SIGNATURE = 504;
+ uint256 internal constant EXIT_BELOW_MIN = 505;
+ uint256 internal constant JOIN_ABOVE_MAX = 506;
+ uint256 internal constant SWAP_LIMIT = 507;
+ uint256 internal constant SWAP_DEADLINE = 508;
+ uint256 internal constant CANNOT_SWAP_SAME_TOKEN = 509;
+ uint256 internal constant UNKNOWN_AMOUNT_IN_FIRST_SWAP = 510;
+ uint256 internal constant MALCONSTRUCTED_MULTIHOP_SWAP = 511;
+ uint256 internal constant INTERNAL_BALANCE_OVERFLOW = 512;
+ uint256 internal constant INSUFFICIENT_INTERNAL_BALANCE = 513;
+ uint256 internal constant INVALID_ETH_INTERNAL_BALANCE = 514;
+ uint256 internal constant INVALID_POST_LOAN_BALANCE = 515;
+ uint256 internal constant INSUFFICIENT_ETH = 516;
+ uint256 internal constant UNALLOCATED_ETH = 517;
+ uint256 internal constant ETH_TRANSFER = 518;
+ uint256 internal constant CANNOT_USE_ETH_SENTINEL = 519;
+ uint256 internal constant TOKENS_MISMATCH = 520;
+ uint256 internal constant TOKEN_NOT_REGISTERED = 521;
+ uint256 internal constant TOKEN_ALREADY_REGISTERED = 522;
+ uint256 internal constant TOKENS_ALREADY_SET = 523;
+ uint256 internal constant TOKENS_LENGTH_MUST_BE_2 = 524;
+ uint256 internal constant NONZERO_TOKEN_BALANCE = 525;
+ uint256 internal constant BALANCE_TOTAL_OVERFLOW = 526;
+ uint256 internal constant POOL_NO_TOKENS = 527;
+ uint256 internal constant INSUFFICIENT_FLASH_LOAN_BALANCE = 528;
+
+ // Fees
+ uint256 internal constant SWAP_FEE_PERCENTAGE_TOO_HIGH = 600;
+ uint256 internal constant FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH = 601;
+ uint256 internal constant INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT = 602;
+ uint256 internal constant AUM_FEE_PERCENTAGE_TOO_HIGH = 603;
+
+ // FeeSplitter
+ uint256 internal constant SPLITTER_FEE_PERCENTAGE_TOO_HIGH = 700;
+
+ // Misc
+ uint256 internal constant UNIMPLEMENTED = 998;
+ uint256 internal constant SHOULD_NOT_HAPPEN = 999;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/IAuthentication.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/IAuthentication.sol
new file mode 100644
index 0000000..35ed541
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/IAuthentication.sol
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IAuthentication {
+ /**
+ * @dev Returns the action identifier associated with the external function described by `selector`.
+ */
+ function getActionId(bytes4 selector) external view returns (bytes32);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/IOptionalOnlyCaller.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/IOptionalOnlyCaller.sol
new file mode 100644
index 0000000..adbbcc3
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/IOptionalOnlyCaller.sol
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev Interface for the OptionalOnlyCaller helper, used to opt in to a caller
+ * verification for a given address to methods that are otherwise callable by any address.
+ */
+interface IOptionalOnlyCaller {
+ /**
+ * @dev Emitted every time setOnlyCallerCheck is called.
+ */
+ event OnlyCallerOptIn(address user, bool enabled);
+
+ /**
+ * @dev Enables / disables verification mechanism for caller.
+ * @param enabled - True if caller verification shall be enabled, false otherwise.
+ */
+ function setOnlyCallerCheck(bool enabled) external;
+
+ function setOnlyCallerCheckWithSignature(
+ address user,
+ bool enabled,
+ bytes memory signature
+ ) external;
+
+ /**
+ * @dev Returns true if caller verification is enabled for the given user, false otherwise.
+ */
+ function isOnlyCallerEnabled(address user) external view returns (bool);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ISignaturesValidator.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ISignaturesValidator.sol
new file mode 100644
index 0000000..cd89f24
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ISignaturesValidator.sol
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev Interface for the SignatureValidator helper, used to support meta-transactions.
+ */
+interface ISignaturesValidator {
+ /**
+ * @dev Returns the EIP712 domain separator.
+ */
+ function getDomainSeparator() external view returns (bytes32);
+
+ /**
+ * @dev Returns the next nonce used by an address to sign messages.
+ */
+ function getNextNonce(address user) external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ITemporarilyPausable.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ITemporarilyPausable.sol
new file mode 100644
index 0000000..9895f71
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ITemporarilyPausable.sol
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev Interface for the TemporarilyPausable helper.
+ */
+interface ITemporarilyPausable {
+ /**
+ * @dev Emitted every time the pause state changes by `_setPaused`.
+ */
+ event PausedStateChanged(bool paused);
+
+ /**
+ * @dev Returns the current paused state.
+ */
+ function getPausedState()
+ external
+ view
+ returns (
+ bool paused,
+ uint256 pauseWindowEndTime,
+ uint256 bufferPeriodEndTime
+ );
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IERC4626.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IERC4626.sol
new file mode 100644
index 0000000..2f52637
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IERC4626.sol
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../openzeppelin/IERC20.sol";
+
+interface IERC4626 is IERC20 {
+ /**
+ * @dev `caller` has exchanged `assets` for `shares`, and transferred those `shares` to `owner`.
+ */
+ event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
+
+ /**
+ * @dev `caller` has exchanged `shares`, owned by `owner`, for `assets`,
+ * and transferred those `assets` to `receiver`.
+ */
+ event Withdraw(
+ address indexed caller,
+ address indexed receiver,
+ address indexed owner,
+ uint256 assets,
+ uint256 shares
+ );
+
+ /**
+ * @dev Mints `shares` Vault shares to `receiver` by depositing exactly `amount` of underlying tokens.
+ */
+ function deposit(uint256 assets, address receiver) external returns (uint256 shares);
+
+ /**
+ * @dev Burns exactly `shares` from `owner` and sends `assets` of underlying tokens to `receiver`.
+ */
+ function redeem(
+ uint256 shares,
+ address receiver,
+ address owner
+ ) external returns (uint256 assets);
+
+ /**
+ * @dev The address of the underlying token that the Vault uses for accounting, depositing, and withdrawing.
+ */
+ function asset() external view returns (address);
+
+ /**
+ * @dev Total amount of the underlying asset that is “managed” by Vault.
+ */
+ function totalAssets() external view returns (uint256);
+
+ /**
+ * @dev The amount of `assets` that the Vault would exchange for the amount
+ * of `shares` provided, in an ideal scenario where all the conditions are met.
+ */
+ function convertToAssets(uint256 shares) external view returns (uint256 assets);
+
+ /**
+ * @dev The amount of `shares` that the Vault would exchange for the amount
+ * of `assets` provided, in an ideal scenario where all the conditions are met.
+ */
+ function convertToShares(uint256 assets) external view returns (uint256 shares);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IWETH.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IWETH.sol
new file mode 100644
index 0000000..c9a519a
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IWETH.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../openzeppelin/IERC20.sol";
+
+/**
+ * @dev Interface for WETH9.
+ * See https://github.com/gnosis/canonical-weth/blob/0dd1ea3e295eef916d0c6223ec63141137d22d67/contracts/WETH9.sol
+ */
+interface IWETH is IERC20 {
+ function deposit() external payable;
+
+ function withdraw(uint256 amount) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC1271.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC1271.sol
new file mode 100644
index 0000000..bc56e73
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC1271.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev Interface of the ERC1271 standard signature validation method for
+ * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
+ *
+ * _Available since v4.1._
+ */
+interface IERC1271 {
+ /**
+ * @dev Should return whether the signature provided is valid for the provided data
+ * @param hash Hash of the data to be signed
+ * @param signature Signature byte array associated with _data
+ */
+ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol
new file mode 100644
index 0000000..7cd1c14
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev Interface of the ERC20 standard as defined in the EIP.
+ */
+interface IERC20 {
+ /**
+ * @dev Returns the amount of tokens in existence.
+ */
+ function totalSupply() external view returns (uint256);
+
+ /**
+ * @dev Returns the amount of tokens owned by `account`.
+ */
+ function balanceOf(address account) external view returns (uint256);
+
+ /**
+ * @dev Moves `amount` tokens from the caller's account to `recipient`.
+ *
+ * Returns a boolean value indicating whether the operation succeeded.
+ *
+ * Emits a {Transfer} event.
+ */
+ function transfer(address recipient, uint256 amount) external returns (bool);
+
+ /**
+ * @dev Returns the remaining number of tokens that `spender` will be
+ * allowed to spend on behalf of `owner` through {transferFrom}. This is
+ * zero by default.
+ *
+ * This value changes when {approve} or {transferFrom} are called.
+ */
+ function allowance(address owner, address spender) external view returns (uint256);
+
+ /**
+ * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
+ *
+ * Returns a boolean value indicating whether the operation succeeded.
+ *
+ * IMPORTANT: Beware that changing an allowance with this method brings the risk
+ * that someone may use both the old and the new allowance by unfortunate
+ * transaction ordering. One possible solution to mitigate this race
+ * condition is to first reduce the spender's allowance to 0 and set the
+ * desired value afterwards:
+ * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
+ *
+ * Emits an {Approval} event.
+ */
+ function approve(address spender, uint256 amount) external returns (bool);
+
+ /**
+ * @dev Moves `amount` tokens from `sender` to `recipient` using the
+ * allowance mechanism. `amount` is then deducted from the caller's
+ * allowance.
+ *
+ * Returns a boolean value indicating whether the operation succeeded.
+ *
+ * Emits a {Transfer} event.
+ */
+ function transferFrom(
+ address sender,
+ address recipient,
+ uint256 amount
+ ) external returns (bool);
+
+ /**
+ * @dev Emitted when `value` tokens are moved from one account (`from`) to
+ * another (`to`).
+ *
+ * Note that `value` may be zero.
+ */
+ event Transfer(address indexed from, address indexed to, uint256 value);
+
+ /**
+ * @dev Emitted when the allowance of a `spender` for an `owner` is set by
+ * a call to {approve}. `value` is the new allowance.
+ */
+ event Approval(address indexed owner, address indexed spender, uint256 value);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20Permit.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20Permit.sol
new file mode 100644
index 0000000..0259cbb
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20Permit.sol
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
+ * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
+ *
+ * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
+ * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
+ * need to send a transaction, and thus is not required to hold Ether at all.
+ */
+interface IERC20Permit {
+ /**
+ * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
+ * given `owner`'s signed approval.
+ *
+ * IMPORTANT: The same issues {IERC20-approve} has related to transaction
+ * ordering also apply here.
+ *
+ * Emits an {Approval} event.
+ *
+ * Requirements:
+ *
+ * - `spender` cannot be the zero address.
+ * - `deadline` must be a timestamp in the future.
+ * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
+ * over the EIP712-formatted function arguments.
+ * - the signature must use ``owner``'s current nonce (see {nonces}).
+ *
+ * For more information on the signature format, see the
+ * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
+ * section].
+ */
+ function permit(
+ address owner,
+ address spender,
+ uint256 value,
+ uint256 deadline,
+ uint8 v,
+ bytes32 r,
+ bytes32 s
+ ) external;
+
+ /**
+ * @dev Returns the current nonce for `owner`. This value must be
+ * included whenever a signature is generated for {permit}.
+ *
+ * Every successful call to {permit} increases ``owner``'s nonce by one. This
+ * prevents a signature from being used multiple times.
+ */
+ function nonces(address owner) external view returns (uint256);
+
+ /**
+ * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
+ */
+ // solhint-disable-next-line func-name-mixedcase
+ function DOMAIN_SEPARATOR() external view returns (bytes32);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20PermitDAI.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20PermitDAI.sol
new file mode 100644
index 0000000..e69d98b
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20PermitDAI.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IERC20PermitDAI {
+ /**
+ * @notice update allowance with a signed permit
+ * @param holder Token owner's address (Authorizer)
+ * @param spender Spender's address
+ * @param nonce The permit nonce
+ * @param expiry The time at which this expires (unix time)
+ * @param allowed Whether the spender is allowed or disallowed from spending
+ * @param v v of the signature
+ * @param r r of the signature
+ * @param s s of the signature
+ */
+ function permit(
+ address holder,
+ address spender,
+ uint256 nonce,
+ uint256 expiry,
+ bool allowed,
+ uint8 v,
+ bytes32 r,
+ bytes32 s
+ ) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/LICENSE b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/LICENSE
new file mode 100644
index 0000000..ade2b70
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2020 zOS Global Limited
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/README.md b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/README.md
new file mode 100644
index 0000000..98659b1
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/README.md
@@ -0,0 +1,11 @@
+## Ports from OpenZeppelin Contracts
+
+Files in this directory are based on the [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) library, and as such are licensed under the MIT License: see [LICENSE](./LICENSE).
+
+Most of the modifications fall under one of these categories:
+
+- removal of functions unused in Balancer V2 source code
+- replacement of `require` statements with the `_require` function from the `BalancerErrors.sol` contract
+- modification or addition of functionality to reduce bytecode size (see `ReentrancyGuard.sol`) or gas usage (see `EnumerableSet`, `EnumerableMap` or `SafeERC20`)
+
+Non-trivial modifications in this last category have associated source code comments that explain the changes and motivation.
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IAToken.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IAToken.sol
new file mode 100644
index 0000000..6b2ca63
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IAToken.sol
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IAToken {
+ /**
+ * @dev returns the address of the aToken's underlying asset
+ */
+ // solhint-disable-next-line func-name-mixedcase
+ function UNDERLYING_ASSET_ADDRESS() external view returns (address);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBALTokenHolder.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBALTokenHolder.sol
new file mode 100644
index 0000000..a73613c
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBALTokenHolder.sol
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/helpers/IAuthentication.sol";
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface IBALTokenHolder is IAuthentication {
+ function getName() external view returns (string memory);
+
+ function withdrawFunds(address recipient, uint256 amount) external;
+
+ function sweepTokens(
+ IERC20 token,
+ address recipient,
+ uint256 amount
+ ) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBALTokenHolderFactory.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBALTokenHolderFactory.sol
new file mode 100644
index 0000000..0836b96
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBALTokenHolderFactory.sol
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../vault/IVault.sol";
+import "../liquidity-mining/IBalancerToken.sol";
+
+import "./IBALTokenHolder.sol";
+
+interface IBALTokenHolderFactory {
+ function getBalancerToken() external view returns (IBalancerToken);
+
+ function getVault() external view returns (IVault);
+
+ function isHolderFromFactory(address holder) external view returns (bool);
+
+ function create(string memory name) external returns (IBALTokenHolder);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBalancerQueries.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBalancerQueries.sol
new file mode 100644
index 0000000..435f0ea
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBalancerQueries.sol
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../vault/IVault.sol";
+
+/**
+ * @dev Provides a way to perform queries on swaps, joins and exits, simulating these operations and returning the exact
+ * result they would have if called on the Vault given the current state. Note that the results will be affected by
+ * other transactions interacting with the Pools involved.
+ *
+ * All query functions can be called both on-chain and off-chain.
+ *
+ * If calling them from a contract, note that all query functions are not `view`. Despite this, these functions produce
+ * no net state change, and for all intents and purposes can be thought of as if they were indeed `view`. However,
+ * calling them via STATICCALL will fail.
+ *
+ * If calling them from an off-chain client, make sure to use eth_call: most clients default to eth_sendTransaction for
+ * non-view functions.
+ *
+ * In all cases, the `fromInternalBalance` and `toInternalBalance` fields are entirely ignored: we just use the same
+ * structs for simplicity.
+ */
+interface IBalancerQueries {
+ function querySwap(IVault.SingleSwap memory singleSwap, IVault.FundManagement memory funds)
+ external
+ returns (uint256);
+
+ function queryBatchSwap(
+ IVault.SwapKind kind,
+ IVault.BatchSwapStep[] memory swaps,
+ IAsset[] memory assets,
+ IVault.FundManagement memory funds
+ ) external returns (int256[] memory assetDeltas);
+
+ function queryJoin(
+ bytes32 poolId,
+ address sender,
+ address recipient,
+ IVault.JoinPoolRequest memory request
+ ) external returns (uint256 bptOut, uint256[] memory amountsIn);
+
+ function queryExit(
+ bytes32 poolId,
+ address sender,
+ address recipient,
+ IVault.ExitPoolRequest memory request
+ ) external returns (uint256 bptIn, uint256[] memory amountsOut);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBalancerRelayer.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBalancerRelayer.sol
new file mode 100644
index 0000000..57b93fc
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IBalancerRelayer.sol
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../vault/IVault.sol";
+
+/**
+ * @title IBalancerRelayer
+ * @notice Allows safe multicall execution of a relayer's functions
+ */
+interface IBalancerRelayer {
+ function getLibrary() external view returns (address);
+
+ function getVault() external view returns (IVault);
+
+ function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IButtonWrapper.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IButtonWrapper.sol
new file mode 100644
index 0000000..b4473e8
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IButtonWrapper.sol
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+// Source: https://github.com/buttonwood-protocol/button-wrappers/blob/main/contracts/interfaces/IButtonWrapper.sol
+// Interface definition for ButtonWrapper contract, which wraps an
+// underlying ERC20 token into a new ERC20 with different characteristics.
+// NOTE: "uAmount" => underlying token (wrapped) amount and
+// "amount" => wrapper token amount
+interface IButtonWrapper {
+ //--------------------------------------------------------------------------
+ // ButtonWrapper write methods
+
+ /// @notice Transfers underlying tokens from {msg.sender} to the contract and
+ /// mints wrapper tokens.
+ /// @param amount The amount of wrapper tokens to mint.
+ /// @return The amount of underlying tokens deposited.
+ function mint(uint256 amount) external returns (uint256);
+
+ /// @notice Transfers underlying tokens from {msg.sender} to the contract and
+ /// mints wrapper tokens to the specified beneficiary.
+ /// @param to The beneficiary account.
+ /// @param amount The amount of wrapper tokens to mint.
+ /// @return The amount of underlying tokens deposited.
+ function mintFor(address to, uint256 amount) external returns (uint256);
+
+ /// @notice Burns wrapper tokens from {msg.sender} and transfers
+ /// the underlying tokens back.
+ /// @param amount The amount of wrapper tokens to burn.
+ /// @return The amount of underlying tokens withdrawn.
+ function burn(uint256 amount) external returns (uint256);
+
+ /// @notice Burns wrapper tokens from {msg.sender} and transfers
+ /// the underlying tokens to the specified beneficiary.
+ /// @param to The beneficiary account.
+ /// @param amount The amount of wrapper tokens to burn.
+ /// @return The amount of underlying tokens withdrawn.
+ function burnTo(address to, uint256 amount) external returns (uint256);
+
+ /// @notice Burns all wrapper tokens from {msg.sender} and transfers
+ /// the underlying tokens back.
+ /// @return The amount of underlying tokens withdrawn.
+ function burnAll() external returns (uint256);
+
+ /// @notice Burns all wrapper tokens from {msg.sender} and transfers
+ /// the underlying tokens back.
+ /// @param to The beneficiary account.
+ /// @return The amount of underlying tokens withdrawn.
+ function burnAllTo(address to) external returns (uint256);
+
+ /// @notice Transfers underlying tokens from {msg.sender} to the contract and
+ /// mints wrapper tokens to the specified beneficiary.
+ /// @param uAmount The amount of underlying tokens to deposit.
+ /// @return The amount of wrapper tokens mint.
+ function deposit(uint256 uAmount) external returns (uint256);
+
+ /// @notice Transfers underlying tokens from {msg.sender} to the contract and
+ /// mints wrapper tokens to the specified beneficiary.
+ /// @param to The beneficiary account.
+ /// @param uAmount The amount of underlying tokens to deposit.
+ /// @return The amount of wrapper tokens mint.
+ function depositFor(address to, uint256 uAmount) external returns (uint256);
+
+ /// @notice Burns wrapper tokens from {msg.sender} and transfers
+ /// the underlying tokens back.
+ /// @param uAmount The amount of underlying tokens to withdraw.
+ /// @return The amount of wrapper tokens burnt.
+ function withdraw(uint256 uAmount) external returns (uint256);
+
+ /// @notice Burns wrapper tokens from {msg.sender} and transfers
+ /// the underlying tokens back to the specified beneficiary.
+ /// @param to The beneficiary account.
+ /// @param uAmount The amount of underlying tokens to withdraw.
+ /// @return The amount of wrapper tokens burnt.
+ function withdrawTo(address to, uint256 uAmount) external returns (uint256);
+
+ /// @notice Burns all wrapper tokens from {msg.sender} and transfers
+ /// the underlying tokens back.
+ /// @return The amount of wrapper tokens burnt.
+ function withdrawAll() external returns (uint256);
+
+ /// @notice Burns all wrapper tokens from {msg.sender} and transfers
+ /// the underlying tokens back.
+ /// @param to The beneficiary account.
+ /// @return The amount of wrapper tokens burnt.
+ function withdrawAllTo(address to) external returns (uint256);
+
+ //--------------------------------------------------------------------------
+ // ButtonWrapper view methods
+
+ /// @return The address of the underlying token.
+ function underlying() external view returns (address);
+
+ /// @return The total underlying tokens held by the wrapper contract.
+ function totalUnderlying() external view returns (uint256);
+
+ /// @param who The account address.
+ /// @return The underlying token balance of the account.
+ function balanceOfUnderlying(address who) external view returns (uint256);
+
+ /// @param uAmount The amount of underlying tokens.
+ /// @return The amount of wrapper tokens exchangeable.
+ function underlyingToWrapper(uint256 uAmount) external view returns (uint256);
+
+ /// @param amount The amount of wrapper tokens.
+ /// @return The amount of underlying tokens exchangeable.
+ function wrapperToUnderlying(uint256 amount) external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ICToken.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ICToken.sol
new file mode 100644
index 0000000..0473a01
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ICToken.sol
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity ^0.7.0;
+
+// Interface for MidasCapital. An open interest protocol based on
+// modified Fuse contracts. Anyone can create an deploy isolated
+// lending and borrowing pools with custom parameters.
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface ICToken is IERC20 {
+ // Error codes referenced in this file can be found here:
+ // https://github.com/compound-finance/compound-protocol/blob/a3214f67b73310d547e00fc578e8355911c9d376/contracts/ErrorReporter.sol
+ // solhint-disable-previous-line max-line-length
+
+ /**
+ * @dev Underlying asset for this CToken
+ */
+ function underlying() external view returns (address);
+
+ /**
+ * @notice Sender supplies assets into the market and receives cTokens in exchange
+ * @dev Accrues interest whether or not the operation succeeds, unless reverted
+ * @param mintAmount The amount of the underlying asset to supply
+ * @return uint 0=success, otherwise an error code (see ErrorReporter.sol link above for details)
+ */
+ function mint(uint256 mintAmount) external returns (uint256);
+
+ /**
+ * @notice Sender redeems cTokens in exchange for the underlying asset
+ * @dev Accrues interest whether or not the operation succeeds, unless reverted
+ * @param redeemTokens The number of cTokens to redeem into underlying
+ * @return uint 0=success, otherwise an error code (see ErrorReporter.sol link above for details)
+ */
+ function redeem(uint256 redeemTokens) external returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IEulerToken.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IEulerToken.sol
new file mode 100644
index 0000000..2cf453e
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IEulerToken.sol
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity ^0.7.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface IEulerToken is IERC20 {
+ /**
+ * @dev Convert an eToken balance to an underlying amount, taking into account current exchange rate
+ * @param balance eToken balance, in internal book-keeping units (18 decimals)
+ * @return Amount in underlying units, (same decimals as underlying token)
+ */
+ // https://github.com/euler-xyz/euler-contracts/blob/b1ee3265853628d5a529081d7908c38404201b4e/contracts/modules/EToken.sol#L104
+ // solhint-disable-previous-line max-line-length
+ function convertBalanceToUnderlying(uint256 balance) external view returns (uint256);
+
+ /**
+ * @dev Convert an underlying amount to an eToken balance, taking into account current exchange rate
+ * @param underlyingAmount Amount in underlying units (same decimals as underlying token)
+ * @return eToken balance, in internal book-keeping units (18 decimals)
+ */
+ // https://github.com/euler-xyz/euler-contracts/blob/b1ee3265853628d5a529081d7908c38404201b4e/contracts/modules/EToken.sol#L114
+ // solhint-disable-previous-line max-line-length
+ function convertUnderlyingToBalance(uint256 underlyingAmount) external view returns (uint256);
+
+ /**
+ * @dev Transfer underlying tokens from sender to the Euler pool, and increase account's eTokens
+ */
+ function deposit(uint256 subAccountId, uint256 amount) external;
+
+ /**
+ * @dev Transfer underlying tokens from Euler pool to sender, and decrease account's eTokens
+ */
+ function withdraw(uint256 subAccountId, uint256 amount) external;
+
+ /**
+ * @dev Address of underlying asset
+ */
+ function underlyingAsset() external view returns (address);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IGearboxDieselToken.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IGearboxDieselToken.sol
new file mode 100644
index 0000000..04241de
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IGearboxDieselToken.sol
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface IGearboxDieselToken is IERC20 {
+ /**
+ * @dev returns the address of the vault
+ */
+ function owner() external view returns (address);
+}
+
+interface IGearboxVault {
+ /**
+ * @dev returns the address of the underlying asset
+ */
+ function underlyingToken() external view returns (address);
+
+ /**
+ * @dev returns a 27 decimal fixed point 'ray' value so a rate of 1 is represented as 1e27
+ */
+ // solhint-disable-next-line func-name-mixedcase
+ function getDieselRate_RAY() external view returns (uint256);
+
+ /**
+ * @dev converts diesel token amount to main token amount
+ */
+ function fromDiesel(uint256) external view returns (uint256);
+
+ /**
+ * @dev converts main token amount to diesel token amount
+ */
+ function toDiesel(uint256) external view returns (uint256);
+
+ /**
+ * @dev Adds liquidity to pool and sends diesel (LP) tokens back to the liquidity provider
+ * The Referral code can be 0
+ */
+ function addLiquidity(
+ uint256 underlyingAmount,
+ address onBehalfOf,
+ uint256 referralCode
+ ) external;
+
+ /**
+ * @dev Removes liquidity from the pool and sends the underlying tokens to the `to` address
+ */
+ function removeLiquidity(uint256 dieselAmount, address to) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeePercentagesProvider.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeePercentagesProvider.sol
new file mode 100644
index 0000000..d368079
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeePercentagesProvider.sol
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+/**
+ * @dev Source of truth for all Protocol Fee percentages, that is, how much the protocol charges certain actions. Some
+ * of these values may also be retrievable from other places (such as the swap fee percentage), but this is the
+ * preferred source nonetheless.
+ */
+interface IProtocolFeePercentagesProvider {
+ // All fee percentages are 18-decimal fixed point numbers, so e.g. 1e18 = 100% and 1e16 = 1%.
+
+ // Emitted when a new fee type is registered.
+ event ProtocolFeeTypeRegistered(uint256 indexed feeType, string name, uint256 maximumPercentage);
+
+ // Emitted when the value of a fee type changes.
+ // IMPORTANT: it is possible for a third party to modify the SWAP and FLASH_LOAN fee type values directly in the
+ // ProtocolFeesCollector, which will result in this event not being emitted despite their value changing. Such usage
+ // of the ProtocolFeesCollector is however discouraged: all state-changing interactions with it should originate in
+ // this contract.
+ event ProtocolFeePercentageChanged(uint256 indexed feeType, uint256 percentage);
+
+ /**
+ * @dev Registers a new fee type in the system, making it queryable via `getFeeTypePercentage` and `getFeeTypeName`,
+ * as well as configurable via `setFeeTypePercentage`.
+ *
+ * `feeType` can be any arbitrary value (that is not in use).
+ *
+ * It is not possible to de-register fee types, nor change their name or maximum value.
+ */
+ function registerFeeType(
+ uint256 feeType,
+ string memory name,
+ uint256 maximumValue,
+ uint256 initialValue
+ ) external;
+
+ /**
+ * @dev Returns true if `feeType` has been registered and can be queried.
+ */
+ function isValidFeeType(uint256 feeType) external view returns (bool);
+
+ /**
+ * @dev Returns true if `value` is a valid percentage value for `feeType`.
+ */
+ function isValidFeeTypePercentage(uint256 feeType, uint256 value) external view returns (bool);
+
+ /**
+ * @dev Sets the percentage value for `feeType` to `newValue`.
+ *
+ * IMPORTANT: it is possible for a third party to modify the SWAP and FLASH_LOAN fee type values directly in the
+ * ProtocolFeesCollector, without invoking this function. This will result in the `ProtocolFeePercentageChanged`
+ * event not being emitted despite their value changing. Such usage of the ProtocolFeesCollector is however
+ * discouraged: only this contract should be granted permission to call `setSwapFeePercentage` and
+ * `setFlashLoanFeePercentage`.
+ */
+ function setFeeTypePercentage(uint256 feeType, uint256 newValue) external;
+
+ /**
+ * @dev Returns the current percentage value for `feeType`. This is the preferred mechanism for querying these -
+ * whenever possible, use this fucntion instead of e.g. querying the ProtocolFeesCollector.
+ */
+ function getFeeTypePercentage(uint256 feeType) external view returns (uint256);
+
+ /**
+ * @dev Returns `feeType`'s maximum value.
+ */
+ function getFeeTypeMaximumPercentage(uint256 feeType) external view returns (uint256);
+
+ /**
+ * @dev Returns `feeType`'s name.
+ */
+ function getFeeTypeName(uint256 feeType) external view returns (string memory);
+}
+
+library ProtocolFeeType {
+ // This list is not exhaustive - more fee types can be added to the system. It is expected for this list to be
+ // extended with new fee types as they are registered, to keep them all in one place and reduce
+ // likelihood of user error.
+
+ // solhint-disable private-vars-leading-underscore
+ uint256 internal constant SWAP = 0;
+ uint256 internal constant FLASH_LOAN = 1;
+ uint256 internal constant YIELD = 2;
+ uint256 internal constant AUM = 3;
+ // solhint-enable private-vars-leading-underscore
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeeSplitter.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeeSplitter.sol
new file mode 100644
index 0000000..934d262
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeeSplitter.sol
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../vault/IVault.sol";
+import "./IProtocolFeesWithdrawer.sol";
+
+/**
+ * @title ProtocolFeeSplitter
+ * @author Daoism Systems
+ * @notice Distributes protocol fees collected from a particular pool between a DAO fund recipient
+ * (e.g., the Balancer DAO treasury), and a beneficiary designated by the pool owner.
+ * @dev By default, all funds go to the DAO. To claim a share of the protocol fees, pool owners
+ * may call `setPoolBeneficiary`.
+ */
+interface IProtocolFeeSplitter {
+ event FeesCollected(
+ bytes32 indexed poolId,
+ address indexed beneficiary,
+ uint256 poolEarned,
+ address indexed daoFundsRecipient,
+ uint256 daoEarned
+ );
+
+ event PoolRevenueShareChanged(bytes32 indexed poolId, uint256 revenueSharePercentage);
+ event PoolRevenueShareCleared(bytes32 indexed poolId);
+ event PoolBeneficiaryChanged(bytes32 indexed poolId, address newBeneficiary);
+ event DefaultRevenueSharePercentageChanged(uint256 revenueSharePercentage);
+ event DAOFundsRecipientChanged(address newDaoFundsRecipient);
+
+ // Fund recipients
+
+ /**
+ * @notice Returns the DAO funds recipient that will receive any balance not due to the pool beneficiary.
+ */
+ function getDaoFundsRecipient() external view returns (address);
+
+ /**
+ * @notice Allows a authorized user to change the DAO funds recipient.
+ * @dev This is a permissioned function.
+ * @param newDaoFundsRecipient - address of the new DAO funds recipient.
+ */
+ function setDaoFundsRecipient(address newDaoFundsRecipient) external;
+
+ /**
+ * @notice Allows a pool owner to change the revenue share beneficiary for a given pool.
+ * @dev This is a permissioned function.
+ * @param poolId - the poolId of the pool where the beneficiary will change.
+ * @param newBeneficiary - address of the new beneficiary.
+ */
+ function setPoolBeneficiary(bytes32 poolId, address newBeneficiary) external;
+
+ // Revenue share settings
+
+ /**
+ * @dev Returns the current protocol fee split configuration for a given pool.
+ * @param poolId - the poolId of a pool with accrued protocol fees.
+ * @return revenueSharePercentageOverride - the percentage of the split sent to the pool beneficiary.
+ * @return beneficiary - the address of the pool beneficiary.
+ */
+ function getRevenueShareSettings(bytes32 poolId)
+ external
+ view
+ returns (
+ uint256 revenueSharePercentageOverride,
+ address beneficiary,
+ bool overrideSet
+ );
+
+ /**
+ * @dev Returns the default revenue share percentage a pool will receive, unless overridden by a call
+ * to `setRevenueSharePercentage`.
+ */
+ function getDefaultRevenueSharePercentage() external view returns (uint256);
+
+ /**
+ * @notice Allows an authorized user to change the default revenue share percentage.
+ * @dev Set the default revenue share percentage, applied to pools where no override has been set
+ * through `setRevenueSharePercentage`. Must be below the maximum allowed split.
+ * This is a permissioned function.
+ * @param defaultRevenueSharePercentage - new default revenue share percentage
+ */
+ function setDefaultRevenueSharePercentage(uint256 defaultRevenueSharePercentage) external;
+
+ /**
+ * @notice Allows an authorized user to change the revenueShare for a given pool.
+ * @dev This is a permissioned function.
+ * @param poolId - the poolId of the pool where the revenue share will change.
+ * @param revenueSharePercentage - the new revenue share percentage.
+ */
+ function setRevenueSharePercentage(bytes32 poolId, uint256 revenueSharePercentage) external;
+
+ /**
+ * @notice Allows an authorized user to change the revenueShare for a given pool.
+ * @dev This is a permissioned function.
+ * @param poolId - the poolId of the pool where the revenue share will change.
+ */
+ function clearRevenueSharePercentage(bytes32 poolId) external;
+
+ // Permissionless fee collection functions
+
+ /**
+ * @dev Returns the amount of fees that would be sent to each beneficiary in a call to `collectFees`.
+ * @param poolId - the poolId of a pool with accrued protocol fees.
+ * @return beneficiaryAmount - the BPT amount that would be sent to the pool beneficiary.
+ * @return daoAmount - the BPT amount that would be sent to the DAO funds recipient.
+ */
+ function getAmounts(bytes32 poolId) external view returns (uint256 beneficiaryAmount, uint256 daoAmount);
+
+ /**
+ * @dev Permissionless function to collect and distribute any accrued protocol fees for the given pool.
+ * @param poolId - the poolId of a pool with accrued protocol fees.
+ * @return beneficiaryAmount - the BPT amount sent to the pool beneficiary.
+ * @return daoAmount - the BPT amount sent to the DAO funds recipient.
+ */
+ function collectFees(bytes32 poolId) external returns (uint256 beneficiaryAmount, uint256 daoAmount);
+
+ // Misc getters
+
+ /**
+ * @notice Returns the `ProtocolFeesWithdrawer`, used to withdraw funds from the `ProtocolFeesCollector`.
+ */
+ function getProtocolFeesWithdrawer() external view returns (IProtocolFeesWithdrawer);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeesWithdrawer.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeesWithdrawer.sol
new file mode 100644
index 0000000..04272ce
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolFeesWithdrawer.sol
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../vault/IProtocolFeesCollector.sol";
+
+/**
+ * @author Balancer Labs
+ * @title Protocol Fees Withdrawer
+ * @notice Safety layer around the Protocol Fees Collector which allows withdrawals of specific tokens to be blocked.
+ * This is useful for the case in where tokens that shouldn't be distributed are unexpectedly paid into the Protocol
+ * Fees Collector.
+ */
+interface IProtocolFeesWithdrawer {
+ event TokenAllowlisted(IERC20 token);
+ event TokenDenylisted(IERC20 token);
+
+ /**
+ * @notice Returns the address of the Protocol Fee Collector.
+ */
+ function getProtocolFeesCollector() external view returns (IProtocolFeesCollector);
+
+ /**
+ * @notice Returns whether the provided token may be withdrawn from the Protocol Fee Collector
+ */
+ function isWithdrawableToken(IERC20 token) external view returns (bool);
+
+ /**
+ * @notice Returns whether the provided array of tokens may be withdrawn from the Protocol Fee Collector
+ * @dev Returns false if any token is denylisted.
+ */
+ function isWithdrawableTokens(IERC20[] calldata tokens) external view returns (bool);
+
+ /**
+ * @notice Returns the denylisted token at the given `index`.
+ */
+ function getDenylistedToken(uint256 index) external view returns (IERC20);
+
+ /**
+ * @notice Returns the number of denylisted tokens.
+ */
+ function getDenylistedTokensLength() external view returns (uint256);
+
+ /**
+ * @notice Withdraws fees from the Protocol Fee Collector.
+ * @dev Reverts if attempting to withdraw a denylisted token.
+ * @param tokens - an array of token addresses to withdraw.
+ * @param amounts - an array of the amounts of each token to withdraw.
+ * @param recipient - the address to which to send the withdrawn tokens.
+ */
+ function withdrawCollectedFees(
+ IERC20[] calldata tokens,
+ uint256[] calldata amounts,
+ address recipient
+ ) external;
+
+ /**
+ * @notice Marks the provided token as ineligible for withdrawal from the Protocol Fee Collector
+ */
+ function denylistToken(IERC20 token) external;
+
+ /**
+ * @notice Marks the provided token as eligible for withdrawal from the Protocol Fee Collector
+ */
+ function allowlistToken(IERC20 token) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolIdRegistry.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolIdRegistry.sol
new file mode 100644
index 0000000..4aafa79
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IProtocolIdRegistry.sol
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity ^0.7.0;
+
+/**
+ * @dev Registry of protocol IDs for external integrations with Balancer. The IDs chosen are arbitrary and do not affect
+ * behavior of any Balancer contracts. They are used only to tag specific contracts (usually pools) at the data layer.
+ */
+interface IProtocolIdRegistry {
+ // Emitted when a new protocol ID is registered.
+ event ProtocolIdRegistered(uint256 indexed protocolId, string name);
+
+ // Emitted when a protocol IDs name has been updated.
+ event ProtocolIdRenamed(uint256 indexed protocolId, string name);
+
+ /**
+ * @dev Registers an ID (and name) to differentiate among protocols. Protocol IDs cannot be deregistered.
+ */
+ function registerProtocolId(uint256 protocolId, string memory name) external;
+
+ /**
+ * @dev Changes the name of an existing protocol ID. Should only be used to update in the case of mistakes.
+ */
+ function renameProtocolId(uint256 protocolId, string memory newName) external;
+
+ /**
+ * @dev Returns true if `protocolId` has been registered and can be queried.
+ */
+ function isValidProtocolId(uint256 protocolId) external view returns (bool);
+
+ /**
+ * @dev Returns the name associated with a given `protocolId`.
+ */
+ function getProtocolName(uint256 protocolId) external view returns (string memory);
+}
+
+library ProtocolId {
+ // This list is not exhaustive - more protocol IDs can be added to the system. It is expected for this list to be
+ // extended with new protocol IDs as they are registered, to keep them all in one place and reduce
+ // likelihood of user error.
+ // solhint-disable private-vars-leading-underscore
+ uint256 internal constant AAVE_V1 = 0;
+ uint256 internal constant AAVE_V2 = 1;
+ uint256 internal constant AAVE_V3 = 2;
+ uint256 internal constant AMPLEFORTH = 3;
+ uint256 internal constant BEEFY = 4;
+ uint256 internal constant EULER = 5;
+ uint256 internal constant GEARBOX = 6;
+ uint256 internal constant IDLE = 7;
+ uint256 internal constant MORPHO = 8;
+ uint256 internal constant RADIANT = 9;
+ uint256 internal constant REAPER = 10;
+ uint256 internal constant SILO = 11;
+ uint256 internal constant STARGATE = 12;
+ uint256 internal constant STURDY = 13;
+ uint256 internal constant TESSERA = 14;
+ uint256 internal constant TETU = 15;
+ uint256 internal constant YEARN = 16;
+ uint256 internal constant MIDAS = 17;
+ uint256 internal constant AGAVE = 18;
+ // solhint-enable private-vars-leading-underscore
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IReaperTokenVault.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IReaperTokenVault.sol
new file mode 100644
index 0000000..1f3df5a
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IReaperTokenVault.sol
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+// Source: https://github.com/Byte-Masons/beet-strat/blob/master/contracts/ReaperVaultv1_4.sol
+// Interface definition for the ReaperTokenVault contract, a single strategy vault
+// for Reaper Farm crypts. The pricePerFullShare is always represented with 18 decimals,
+// regardless of the underlying token decimals.
+// ie: If ppfs === 1e18, 1 USDC === 0.000_000_000_001_000_000 rfUSDC
+// ie: If ppfs === 1e18, 1 DAI === 1 rfDAI
+interface IReaperTokenVault is IERC20 {
+ /**
+ * @dev returns the address of the vault's underlying asset (mainToken)
+ */
+ function token() external view returns (address);
+
+ /**
+ * @dev returns the price for a single Vault share (ie rf-scfUSDT). The getPricePerFullShare is always in 1e18
+ */
+ function getPricePerFullShare() external view returns (uint256);
+
+ /**
+ * @notice Deposits `_amount` `token`, issuing shares to the caller.
+ * If Panic is activated, deposits will not be accepted and this call will fail.
+ * @param _amount The quantity of tokens to deposit.
+ **/
+ function deposit(uint256 _amount) external;
+
+ /**
+ * @notice Withdraws the calling account's tokens from this Vault,
+ * redeeming amount `_shares` for an appropriate amount of tokens.
+ **/
+ function withdraw(uint256 _shares) external;
+
+ /**
+ * @dev returns the number of decimals for this vault token.
+ * For reaper single-strat vaults, the decimals are fixed to 18.
+ */
+ function decimals() external view returns (uint8);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IShareToken.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IShareToken.sol
new file mode 100644
index 0000000..0bcfd4e
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IShareToken.sol
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+import "./ISilo.sol";
+
+interface IShareToken is IERC20 {
+ /**
+ * @dev returns the underlying asset
+ */
+ function asset() external view returns (address);
+
+ /**
+ * @dev returns the address of the silo
+ */
+ function silo() external view returns (ISilo);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ISilo.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ISilo.sol
new file mode 100644
index 0000000..7acc7a4
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ISilo.sol
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "./IShareToken.sol";
+
+interface IBaseSilo {
+ /// Storage struct that holds all required data for a single token market
+ struct AssetStorage {
+ // Token that represents a share in totalDeposits of Silo
+ IShareToken collateralToken;
+ // Token that represents a share in collateralOnlyDeposits of Silo
+ IShareToken collateralOnlyToken;
+ // Token that represents a share in totalBorrowAmount of Silo
+ IShareToken debtToken;
+ // COLLATERAL: Amount of asset token that has been deposited to Silo with interest earned by depositors.
+ // It also includes token amount that has been borrowed.
+ uint256 totalDeposits;
+ // COLLATERAL ONLY: Amount of asset token that has been deposited to Silo that can ONLY be used
+ // as collateral. These deposits do NOT earn interest and CANNOT be borrowed.
+ uint256 collateralOnlyDeposits;
+ // DEBT: Amount of asset token that has been borrowed with accrued interest.
+ uint256 totalBorrowAmount;
+ }
+
+ /**
+ * @dev returns the asset storage struct
+ * @dev AssetStorage struct contains necessary information for calculating shareToken exchange rates
+ */
+ function assetStorage(address _asset) external view returns (AssetStorage memory);
+}
+
+interface ISilo is IBaseSilo {
+ /**
+ * @dev Deposits funds into the Silo
+ * @param _asset The address of the token to deposit
+ * @param _depositor The address of the recipient of collateral tokens
+ * @param _amount The amount of the token to deposit
+ * @param _collateralOnly: True means your shareToken is protected (cannot be swapped for interest)
+ * @return collateralAmount deposited amount
+ * @return collateralShare user collateral shares based on deposited amount
+ */
+ function depositFor(
+ address _asset,
+ address _depositor,
+ uint256 _amount,
+ bool _collateralOnly
+ ) external returns (uint256 collateralAmount, uint256 collateralShare);
+
+ /**
+ * @dev Withdraw `_amount` of `_asset` tokens from the Silo to `msg.sender`
+ * @param _asset The address of the token to withdraw
+ * @param _amount The amount of the token to withdraw
+ * @param _collateralOnly True if withdrawing collateral only deposit
+ * @return withdrawnAmount withdrawn amount that was transferred to user
+ * @return withdrawnShare burned share based on `withdrawnAmount`
+ */
+ function withdraw(
+ address _asset,
+ uint256 _amount,
+ bool _collateralOnly
+ ) external returns (uint256 withdrawnAmount, uint256 withdrawnShare);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IStaticATokenLM.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IStaticATokenLM.sol
new file mode 100644
index 0000000..e9125f7
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IStaticATokenLM.sol
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+// solhint-disable-next-line max-line-length
+// Based on https://github.com/aave/protocol-v2/blob/ac58fea62bb8afee23f66197e8bce6d79ecda292/contracts/interfaces/IStaticATokenLM.sol
+
+interface IStaticATokenLM is IERC20 {
+ struct SignatureParams {
+ uint8 v;
+ bytes32 r;
+ bytes32 s;
+ }
+
+ /**
+ * @notice Deposits `ASSET` in the Aave protocol and mints static aTokens to msg.sender
+ * @param recipient The address that will receive the static aTokens
+ * @param amount The amount of underlying `ASSET` to deposit (e.g. deposit of 100 USDC)
+ * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
+ * 0 if the action is executed directly by the user, without any middle-man
+ * @param fromUnderlying bool
+ * - `true` if the msg.sender comes with underlying tokens (e.g. USDC)
+ * - `false` if the msg.sender comes already with aTokens (e.g. aUSDC)
+ * @return uint256 The amount of StaticAToken minted, static balance
+ **/
+ function deposit(
+ address recipient,
+ uint256 amount,
+ uint16 referralCode,
+ bool fromUnderlying
+ ) external returns (uint256);
+
+ /**
+ * @notice Burns `amount` of static aToken, with recipient receiving the corresponding amount of `ASSET`
+ * @param recipient The address that will receive the amount of `ASSET` withdrawn from the Aave protocol
+ * @param amount The amount to withdraw, in static balance of StaticAToken
+ * @param toUnderlying bool
+ * - `true` for the recipient to get underlying tokens (e.g. USDC)
+ * - `false` for the recipient to get aTokens (e.g. aUSDC)
+ * @return amountToBurn: StaticATokens burnt, static balance
+ * @return amountToWithdraw: underlying/aToken send to `recipient`, dynamic balance
+ **/
+ function withdraw(
+ address recipient,
+ uint256 amount,
+ bool toUnderlying
+ ) external returns (uint256, uint256);
+
+ /**
+ * @notice Burns `amount` of static aToken, with recipient receiving the corresponding amount of `ASSET`
+ * @param recipient The address that will receive the amount of `ASSET` withdrawn from the Aave protocol
+ * @param amount The amount to withdraw, in dynamic balance of aToken/underlying asset
+ * @param toUnderlying bool
+ * - `true` for the recipient to get underlying tokens (e.g. USDC)
+ * - `false` for the recipient to get aTokens (e.g. aUSDC)
+ * @return amountToBurn: StaticATokens burnt, static balance
+ * @return amountToWithdraw: underlying/aToken send to `recipient`, dynamic balance
+ **/
+ function withdrawDynamicAmount(
+ address recipient,
+ uint256 amount,
+ bool toUnderlying
+ ) external returns (uint256, uint256);
+
+ /**
+ * @notice Implements the permit function as for
+ * https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
+ * @param owner The owner of the funds
+ * @param spender The spender
+ * @param value The amount
+ * @param deadline The deadline timestamp, type(uint256).max for max deadline
+ * @param v Signature param
+ * @param s Signature param
+ * @param r Signature param
+ */
+ function permit(
+ address owner,
+ address spender,
+ uint256 value,
+ uint256 deadline,
+ uint8 v,
+ bytes32 r,
+ bytes32 s
+ ) external;
+
+ /**
+ * @notice Allows to deposit on Aave via meta-transaction
+ * https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
+ * @param depositor Address from which the funds to deposit are going to be pulled
+ * @param recipient Address that will receive the staticATokens, in the average case, same as the `depositor`
+ * @param value The amount to deposit
+ * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
+ * 0 if the action is executed directly by the user, without any middle-man
+ * @param fromUnderlying bool
+ * - `true` if the msg.sender comes with underlying tokens (e.g. USDC)
+ * - `false` if the msg.sender comes already with aTokens (e.g. aUSDC)
+ * @param deadline The deadline timestamp, type(uint256).max for max deadline
+ * @param sigParams Signature params: v,r,s
+ * @return uint256 The amount of StaticAToken minted, static balance
+ */
+ function metaDeposit(
+ address depositor,
+ address recipient,
+ uint256 value,
+ uint16 referralCode,
+ bool fromUnderlying,
+ uint256 deadline,
+ SignatureParams calldata sigParams
+ ) external returns (uint256);
+
+ /**
+ * @notice Allows to withdraw from Aave via meta-transaction
+ * https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
+ * @param owner Address owning the staticATokens
+ * @param recipient Address that will receive the underlying withdrawn from Aave
+ * @param staticAmount The amount of staticAToken to withdraw. If > 0, `dynamicAmount` needs to be 0
+ * @param dynamicAmount The amount of underlying/aToken to withdraw. If > 0, `staticAmount` needs to be 0
+ * @param toUnderlying bool
+ * - `true` for the recipient to get underlying tokens (e.g. USDC)
+ * - `false` for the recipient to get aTokens (e.g. aUSDC)
+ * @param deadline The deadline timestamp, type(uint256).max for max deadline
+ * @param sigParams Signature params: v,r,s
+ * @return amountToBurn: StaticATokens burnt, static balance
+ * @return amountToWithdraw: underlying/aToken send to `recipient`, dynamic balance
+ */
+ function metaWithdraw(
+ address owner,
+ address recipient,
+ uint256 staticAmount,
+ uint256 dynamicAmount,
+ bool toUnderlying,
+ uint256 deadline,
+ SignatureParams calldata sigParams
+ ) external returns (uint256, uint256);
+
+ /**
+ * @notice Utility method to get the current aToken balance of an user, from his staticAToken balance
+ * @param account The address of the user
+ * @return uint256 The aToken balance
+ **/
+ function dynamicBalanceOf(address account) external view returns (uint256);
+
+ /**
+ * @notice Converts a static amount (scaled balance on aToken) to the aToken/underlying value,
+ * using the current liquidity index on Aave
+ * @param amount The amount to convert from
+ * @return uint256 The dynamic amount
+ **/
+ function staticToDynamicAmount(uint256 amount) external view returns (uint256);
+
+ /**
+ * @notice Converts an aToken or underlying amount to the what it is denominated on the aToken as
+ * scaled balance, function of the principal and the liquidity index
+ * @param amount The amount to convert from
+ * @return uint256 The static (scaled) amount
+ **/
+ function dynamicToStaticAmount(uint256 amount) external view returns (uint256);
+
+ /**
+ * @notice Returns the Aave liquidity index of the underlying aToken, denominated rate here
+ * as it can be considered as an ever-increasing exchange rate
+ * @return The liquidity index
+ **/
+ function rate() external view returns (uint256);
+
+ /**
+ * @notice Function to return a dynamic domain separator, in order to be compatible with forks changing chainId
+ * @return bytes32 The domain separator
+ **/
+ function getDomainSeparator() external view returns (bytes32);
+
+ /**
+ * @notice Claims rewards from `INCENTIVES_CONTROLLER` and updates internal accounting of rewards.
+ */
+ function collectAndUpdateRewards() external;
+
+ /**
+ * @notice Claim rewards on behalf of a user and send them to a receiver
+ * @dev Only callable by if sender is onBehalfOf or sender is approved claimer
+ * @param onBehalfOf The address to claim on behalf of
+ * @param receiver The address to receive the rewards
+ * @param forceUpdate Flag to retrieve latest rewards from `INCENTIVES_CONTROLLER`
+ */
+ function claimRewardsOnBehalf(
+ address onBehalfOf,
+ address receiver,
+ bool forceUpdate
+ ) external;
+
+ /**
+ * @notice Claim rewards and send them to a receiver
+ * @param receiver The address to receive the rewards
+ * @param forceUpdate Flag to retrieve latest rewards from `INCENTIVES_CONTROLLER`
+ */
+ function claimRewards(address receiver, bool forceUpdate) external;
+
+ /**
+ * @notice Claim rewards
+ * @param forceUpdate Flag to retrieve latest rewards from `INCENTIVES_CONTROLLER`
+ */
+ function claimRewardsToSelf(bool forceUpdate) external;
+
+ /**
+ * @notice Get the total claimable rewards of the contract.
+ * @return The current balance + pending rewards from the `_incentivesController`
+ */
+ function getTotalClaimableRewards() external view returns (uint256);
+
+ /**
+ * @notice Get the total claimable rewards for a user in WAD
+ * @param user The address of the user
+ * @return The claimable amount of rewards in WAD
+ */
+ function getClaimableRewards(address user) external view returns (uint256);
+
+ /**
+ * @notice The unclaimed rewards for a user in WAD
+ * @param user The address of the user
+ * @return The unclaimed amount of rewards in WAD
+ */
+ function getUnclaimedRewards(address user) external view returns (uint256);
+
+ function getAccRewardsPerToken() external view returns (uint256);
+
+ function getLifetimeRewardsClaimed() external view returns (uint256);
+
+ function getLifetimeRewards() external view returns (uint256);
+
+ function getLastRewardBlock() external view returns (uint256);
+
+ // solhint-disable-next-line func-name-mixedcase
+ function LENDING_POOL() external returns (address);
+
+ // solhint-disable-next-line func-name-mixedcase
+ function INCENTIVES_CONTROLLER() external returns (address);
+
+ // solhint-disable-next-line func-name-mixedcase
+ function ATOKEN() external returns (IERC20);
+
+ // solhint-disable-next-line func-name-mixedcase
+ function ASSET() external returns (IERC20);
+
+ // solhint-disable-next-line func-name-mixedcase
+ function REWARD_TOKEN() external returns (IERC20);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ITetuSmartVault.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ITetuSmartVault.sol
new file mode 100644
index 0000000..a12a20f
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ITetuSmartVault.sol
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface ITetuSmartVault is IERC20 {
+ function deposit(uint256 amount) external;
+
+ function depositFor(uint256 amount, address holder) external;
+
+ function underlyingBalanceInVault() external view returns (uint256);
+
+ function withdraw(uint256 numberOfShares) external;
+
+ function underlyingBalanceWithInvestmentForHolder(address holder) external view returns (uint256);
+
+ function underlying() external view returns (address);
+
+ function underlyingUnit() external view returns (uint256);
+
+ function getPricePerFullShare() external view returns (uint256);
+
+ function strategy() external view returns (address);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ITetuStrategy.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ITetuStrategy.sol
new file mode 100644
index 0000000..e331dd2
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/ITetuStrategy.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface ITetuStrategy {
+ function investedUnderlyingBalance() external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IUnbuttonToken.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IUnbuttonToken.sol
new file mode 100644
index 0000000..7ee7e6a
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IUnbuttonToken.sol
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+import "./IButtonWrapper.sol";
+
+// Balancer only supports ERC20 tokens, so we use this intermediate interface
+// to enforce ERC20-ness of UnbuttonTokens.
+interface IUnbuttonToken is IButtonWrapper, IERC20 {
+ // solhint-disable-previous-line no-empty-blocks
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IYearnTokenVault.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IYearnTokenVault.sol
new file mode 100644
index 0000000..2f457cc
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IYearnTokenVault.sol
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity ^0.7.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface IYearnTokenVault is IERC20 {
+ /**
+ * @dev returns the address of the vault's underlying asset (mainToken)
+ */
+ function token() external view returns (address);
+
+ /**
+ * @dev returns the price for a single Vault share (ie yvDAI). The pricePerShare is represented
+ * in the same decimals as the underlying asset (ie: 6 decimals for USDC)
+ */
+ function pricePerShare() external view returns (uint256);
+
+ /**
+ * @notice Deposits `_amount` `token`, issuing shares to `recipient`.
+ * If the Vault is in Emergency Shutdown, deposits will not be accepted and this call will fail.
+ * @param _amount The quantity of tokens to deposit, defaults to all.
+ * @param recipient The address to issue the shares in this Vault to. Defaults to the caller's address.
+ * @return The issued Vault shares.
+ */
+ function deposit(uint256 _amount, address recipient) external returns (uint256);
+
+ /**
+ * @notice Withdraws the calling account's tokens from this Vault,
+ * redeeming amount `_shares` for an appropriate amount of tokens.
+ * See note on `setWithdrawalQueue` for further details of withdrawal ordering and behavior.
+ * @param maxShares How many shares to try and redeem for tokens, defaults to all.
+ * @param recipient The address to issue the shares in this Vault to. Defaults to the caller's address.
+ * @return redeemed: The quantity of tokens redeemed for `_shares`.
+ */
+ function withdraw(uint256 maxShares, address recipient) external returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IstETH.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IstETH.sol
new file mode 100644
index 0000000..308e3be
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IstETH.sol
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+// solhint-disable-next-line max-line-length
+// Based on https://github.com/lidofinance/lido-dao/blob/816bf1d0995ba5cfdfc264de4acda34a7fe93eba/contracts/0.4.24/Lido.sol
+
+interface IstETH is IERC20 {
+ function submit(address referral) external payable returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IwstETH.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IwstETH.sol
new file mode 100644
index 0000000..f87bf49
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/standalone-utils/IwstETH.sol
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+import "./IstETH.sol";
+
+// solhint-disable-next-line max-line-length
+// Based on https://github.com/lidofinance/lido-dao/blob/2b46615a11dee77d4d22066f942f6c6afab9b87a/contracts/0.6.12/WstETH.sol
+
+/**
+ * @title StETH token wrapper with static balances.
+ * @dev It's an ERC20 token that represents the account's share of the total
+ * supply of stETH tokens. WstETH token's balance only changes on transfers,
+ * unlike StETH that is also changed when oracles report staking rewards and
+ * penalties. It's a "power user" token for DeFi protocols which don't
+ * support rebasable tokens.
+ *
+ * The contract is also a trustless wrapper that accepts stETH tokens and mints
+ * wstETH in return. Then the user unwraps, the contract burns user's wstETH
+ * and sends user locked stETH in return.
+ *
+ * The contract provides the staking shortcut: user can send ETH with regular
+ * transfer and get wstETH in return. The contract will send ETH to Lido submit
+ * method, staking it and wrapping the received stETH.
+ *
+ */
+interface IwstETH is IERC20 {
+ function stETH() external returns (IstETH);
+
+ /**
+ * @notice Exchanges stETH to wstETH
+ * @param _stETHAmount amount of stETH to wrap in exchange for wstETH
+ * @dev Requirements:
+ * - `_stETHAmount` must be non-zero
+ * - msg.sender must approve at least `_stETHAmount` stETH to this
+ * contract.
+ * - msg.sender must have at least `_stETHAmount` of stETH.
+ * User should first approve _stETHAmount to the WstETH contract
+ * @return Amount of wstETH user receives after wrap
+ */
+ function wrap(uint256 _stETHAmount) external returns (uint256);
+
+ /**
+ * @notice Exchanges wstETH to stETH
+ * @param _wstETHAmount amount of wstETH to uwrap in exchange for stETH
+ * @dev Requirements:
+ * - `_wstETHAmount` must be non-zero
+ * - msg.sender must have at least `_wstETHAmount` wstETH.
+ * @return Amount of stETH user receives after unwrap
+ */
+ function unwrap(uint256 _wstETHAmount) external returns (uint256);
+
+ /**
+ * @notice Get amount of wstETH for a given amount of stETH
+ * @param _stETHAmount amount of stETH
+ * @return Amount of wstETH for a given stETH amount
+ */
+ function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256);
+
+ /**
+ * @notice Get amount of stETH for a given amount of wstETH
+ * @param _wstETHAmount amount of wstETH
+ * @return Amount of stETH for a given wstETH amount
+ */
+ function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256);
+
+ /**
+ * @notice Get amount of wstETH for a one stETH
+ * @return Amount of stETH for 1 wstETH
+ */
+ function stEthPerToken() external view returns (uint256);
+
+ /**
+ * @notice Get amount of stETH for a one wstETH
+ * @return Amount of wstETH for a 1 stETH
+ */
+ function tokensPerStEth() external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IAsset.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IAsset.sol
new file mode 100644
index 0000000..a425a6d
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IAsset.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev This is an empty interface used to represent either ERC20-conforming token contracts or ETH (using the zero
+ * address sentinel value). We're just relying on the fact that `interface` can be used to declare new address-like
+ * types.
+ *
+ * This concept is unrelated to a Pool's Asset Managers.
+ */
+interface IAsset {
+ // solhint-disable-previous-line no-empty-blocks
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IAuthorizer.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IAuthorizer.sol
new file mode 100644
index 0000000..d7995fb
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IAuthorizer.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+interface IAuthorizer {
+ /**
+ * @dev Returns true if `account` can perform the action described by `actionId` in the contract `where`.
+ */
+ function canPerform(
+ bytes32 actionId,
+ address account,
+ address where
+ ) external view returns (bool);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IBasePool.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IBasePool.sol
new file mode 100644
index 0000000..4411e51
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IBasePool.sol
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "./IVault.sol";
+import "./IPoolSwapStructs.sol";
+
+/**
+ * @dev Interface for adding and removing liquidity that all Pool contracts should implement. Note that this is not
+ * the complete Pool contract interface, as it is missing the swap hooks. Pool contracts should also inherit from
+ * either IGeneralPool or IMinimalSwapInfoPool
+ */
+interface IBasePool is IPoolSwapStructs {
+ /**
+ * @dev Called by the Vault when a user calls `IVault.joinPool` to add liquidity to this Pool. Returns how many of
+ * each registered token the user should provide, as well as the amount of protocol fees the Pool owes to the Vault.
+ * The Vault will then take tokens from `sender` and add them to the Pool's balances, as well as collect
+ * the reported amount in protocol fees, which the pool should calculate based on `protocolSwapFeePercentage`.
+ *
+ * Protocol fees are reported and charged on join events so that the Pool is free of debt whenever new users join.
+ *
+ * `sender` is the account performing the join (from which tokens will be withdrawn), and `recipient` is the account
+ * designated to receive any benefits (typically pool shares). `balances` contains the total balances
+ * for each token the Pool registered in the Vault, in the same order that `IVault.getPoolTokens` would return.
+ *
+ * `lastChangeBlock` is the last block in which *any* of the Pool's registered tokens last changed its total
+ * balance.
+ *
+ * `userData` contains any pool-specific instructions needed to perform the calculations, such as the type of
+ * join (e.g., proportional given an amount of pool shares, single-asset, multi-asset, etc.)
+ *
+ * Contracts implementing this function should check that the caller is indeed the Vault before performing any
+ * state-changing operations, such as minting pool shares.
+ */
+ function onJoinPool(
+ bytes32 poolId,
+ address sender,
+ address recipient,
+ uint256[] memory balances,
+ uint256 lastChangeBlock,
+ uint256 protocolSwapFeePercentage,
+ bytes memory userData
+ ) external returns (uint256[] memory amountsIn, uint256[] memory dueProtocolFeeAmounts);
+
+ /**
+ * @dev Called by the Vault when a user calls `IVault.exitPool` to remove liquidity from this Pool. Returns how many
+ * tokens the Vault should deduct from the Pool's balances, as well as the amount of protocol fees the Pool owes
+ * to the Vault. The Vault will then take tokens from the Pool's balances and send them to `recipient`,
+ * as well as collect the reported amount in protocol fees, which the Pool should calculate based on
+ * `protocolSwapFeePercentage`.
+ *
+ * Protocol fees are charged on exit events to guarantee that users exiting the Pool have paid their share.
+ *
+ * `sender` is the account performing the exit (typically the pool shareholder), and `recipient` is the account
+ * to which the Vault will send the proceeds. `balances` contains the total token balances for each token
+ * the Pool registered in the Vault, in the same order that `IVault.getPoolTokens` would return.
+ *
+ * `lastChangeBlock` is the last block in which *any* of the Pool's registered tokens last changed its total
+ * balance.
+ *
+ * `userData` contains any pool-specific instructions needed to perform the calculations, such as the type of
+ * exit (e.g., proportional given an amount of pool shares, single-asset, multi-asset, etc.)
+ *
+ * Contracts implementing this function should check that the caller is indeed the Vault before performing any
+ * state-changing operations, such as burning pool shares.
+ */
+ function onExitPool(
+ bytes32 poolId,
+ address sender,
+ address recipient,
+ uint256[] memory balances,
+ uint256 lastChangeBlock,
+ uint256 protocolSwapFeePercentage,
+ bytes memory userData
+ ) external returns (uint256[] memory amountsOut, uint256[] memory dueProtocolFeeAmounts);
+
+ /**
+ * @dev Returns this Pool's ID, used when interacting with the Vault (to e.g. join the Pool or swap with it).
+ */
+ function getPoolId() external view returns (bytes32);
+
+ /**
+ * @dev Returns the current swap fee percentage as a 18 decimal fixed point number, so e.g. 1e17 corresponds to a
+ * 10% swap fee.
+ */
+ function getSwapFeePercentage() external view returns (uint256);
+
+ /**
+ * @dev Returns the scaling factors of each of the Pool's tokens. This is an implementation detail that is typically
+ * not relevant for outside parties, but which might be useful for some types of Pools.
+ */
+ function getScalingFactors() external view returns (uint256[] memory);
+
+ function queryJoin(
+ bytes32 poolId,
+ address sender,
+ address recipient,
+ uint256[] memory balances,
+ uint256 lastChangeBlock,
+ uint256 protocolSwapFeePercentage,
+ bytes memory userData
+ ) external returns (uint256 bptOut, uint256[] memory amountsIn);
+
+ function queryExit(
+ bytes32 poolId,
+ address sender,
+ address recipient,
+ uint256[] memory balances,
+ uint256 lastChangeBlock,
+ uint256 protocolSwapFeePercentage,
+ bytes memory userData
+ ) external returns (uint256 bptIn, uint256[] memory amountsOut);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IBasicAuthorizer.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IBasicAuthorizer.sol
new file mode 100644
index 0000000..f84bbfb
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IBasicAuthorizer.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+import "./IAuthorizer.sol";
+
+interface IBasicAuthorizer is IAuthorizer {
+ // solhint-disable-next-line func-name-mixedcase
+ function DEFAULT_ADMIN_ROLE() external returns (bytes32);
+
+ function getRoleAdmin(bytes32 role) external view returns (bytes32);
+
+ function getRoleMember(bytes32 role, uint256 index) external view returns (address);
+
+ function getRoleMemberCount(bytes32 role) external view returns (uint256);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol
new file mode 100644
index 0000000..10ad894
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+
+// Inspired by Aave Protocol's IFlashLoanReceiver.
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+interface IFlashLoanRecipient {
+ /**
+ * @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient.
+ *
+ * At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this
+ * call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the
+ * Vault, or else the entire flash loan will revert.
+ *
+ * `userData` is the same value passed in the `IVault.flashLoan` call.
+ */
+ function receiveFlashLoan(
+ IERC20[] memory tokens,
+ uint256[] memory amounts,
+ uint256[] memory feeAmounts,
+ bytes memory userData
+ ) external;
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IGeneralPool.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IGeneralPool.sol
new file mode 100644
index 0000000..e5f2b6b
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IGeneralPool.sol
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "./IBasePool.sol";
+
+/**
+ * @dev IPools with the General specialization setting should implement this interface.
+ *
+ * This is called by the Vault when a user calls `IVault.swap` or `IVault.batchSwap` to swap with this Pool.
+ * Returns the number of tokens the Pool will grant to the user in a 'given in' swap, or that the user will
+ * grant to the pool in a 'given out' swap.
+ *
+ * This can often be implemented by a `view` function, since many pricing algorithms don't need to track state
+ * changes in swaps. However, contracts implementing this in non-view functions should check that the caller is
+ * indeed the Vault.
+ */
+interface IGeneralPool is IBasePool {
+ function onSwap(
+ SwapRequest memory swapRequest,
+ uint256[] memory balances,
+ uint256 indexIn,
+ uint256 indexOut
+ ) external returns (uint256 amount);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IMinimalSwapInfoPool.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IMinimalSwapInfoPool.sol
new file mode 100644
index 0000000..8359396
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IMinimalSwapInfoPool.sol
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "./IBasePool.sol";
+
+/**
+ * @dev Pool contracts with the MinimalSwapInfo or TwoToken specialization settings should implement this interface.
+ *
+ * This is called by the Vault when a user calls `IVault.swap` or `IVault.batchSwap` to swap with this Pool.
+ * Returns the number of tokens the Pool will grant to the user in a 'given in' swap, or that the user will grant
+ * to the pool in a 'given out' swap.
+ *
+ * This can often be implemented by a `view` function, since many pricing algorithms don't need to track state
+ * changes in swaps. However, contracts implementing this in non-view functions should check that the caller is
+ * indeed the Vault.
+ */
+interface IMinimalSwapInfoPool is IBasePool {
+ function onSwap(
+ SwapRequest memory swapRequest,
+ uint256 currentBalanceTokenIn,
+ uint256 currentBalanceTokenOut
+ ) external returns (uint256 amount);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IPoolSwapStructs.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IPoolSwapStructs.sol
new file mode 100644
index 0000000..a23a04d
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IPoolSwapStructs.sol
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+import "./IVault.sol";
+
+interface IPoolSwapStructs {
+ // This is not really an interface - it just defines common structs used by other interfaces: IGeneralPool and
+ // IMinimalSwapInfoPool.
+ //
+ // This data structure represents a request for a token swap, where `kind` indicates the swap type ('given in' or
+ // 'given out') which indicates whether or not the amount sent by the pool is known.
+ //
+ // The pool receives `tokenIn` and sends `tokenOut`. `amount` is the number of `tokenIn` tokens the pool will take
+ // in, or the number of `tokenOut` tokens the Pool will send out, depending on the given swap `kind`.
+ //
+ // All other fields are not strictly necessary for most swaps, but are provided to support advanced scenarios in
+ // some Pools.
+ //
+ // `poolId` is the ID of the Pool involved in the swap - this is useful for Pool contracts that implement more than
+ // one Pool.
+ //
+ // The meaning of `lastChangeBlock` depends on the Pool specialization:
+ // - Two Token or Minimal Swap Info: the last block in which either `tokenIn` or `tokenOut` changed its total
+ // balance.
+ // - General: the last block in which *any* of the Pool's registered tokens changed its total balance.
+ //
+ // `from` is the origin address for the funds the Pool receives, and `to` is the destination address
+ // where the Pool sends the outgoing tokens.
+ //
+ // `userData` is extra data provided by the caller - typically a signature from a trusted party.
+ struct SwapRequest {
+ IVault.SwapKind kind;
+ IERC20 tokenIn;
+ IERC20 tokenOut;
+ uint256 amount;
+ // Misc data
+ bytes32 poolId;
+ uint256 lastChangeBlock;
+ address from;
+ address to;
+ bytes userData;
+ }
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IProtocolFeesCollector.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IProtocolFeesCollector.sol
new file mode 100644
index 0000000..7fb4482
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IProtocolFeesCollector.sol
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.7.0 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+
+import "./IVault.sol";
+import "./IAuthorizer.sol";
+
+interface IProtocolFeesCollector {
+ event SwapFeePercentageChanged(uint256 newSwapFeePercentage);
+ event FlashLoanFeePercentageChanged(uint256 newFlashLoanFeePercentage);
+
+ function withdrawCollectedFees(
+ IERC20[] calldata tokens,
+ uint256[] calldata amounts,
+ address recipient
+ ) external;
+
+ function setSwapFeePercentage(uint256 newSwapFeePercentage) external;
+
+ function setFlashLoanFeePercentage(uint256 newFlashLoanFeePercentage) external;
+
+ function getSwapFeePercentage() external view returns (uint256);
+
+ function getFlashLoanFeePercentage() external view returns (uint256);
+
+ function getCollectedFeeAmounts(IERC20[] memory tokens) external view returns (uint256[] memory feeAmounts);
+
+ function getAuthorizer() external view returns (IAuthorizer);
+
+ function vault() external view returns (IVault);
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IVault.sol b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IVault.sol
new file mode 100644
index 0000000..c55f9d2
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/contracts/vault/IVault.sol
@@ -0,0 +1,772 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma experimental ABIEncoderV2;
+
+import "../solidity-utils/openzeppelin/IERC20.sol";
+import "../solidity-utils/helpers/IAuthentication.sol";
+import "../solidity-utils/helpers/ISignaturesValidator.sol";
+import "../solidity-utils/helpers/ITemporarilyPausable.sol";
+import "../solidity-utils/misc/IWETH.sol";
+
+import "./IAsset.sol";
+import "./IAuthorizer.sol";
+import "./IFlashLoanRecipient.sol";
+import "./IProtocolFeesCollector.sol";
+
+pragma solidity >=0.7.0 <0.9.0;
+
+/**
+ * @dev Full external interface for the Vault core contract - no external or public methods exist in the contract that
+ * don't override one of these declarations.
+ */
+interface IVault is ISignaturesValidator, ITemporarilyPausable, IAuthentication {
+ // Generalities about the Vault:
+ //
+ // - Whenever documentation refers to 'tokens', it strictly refers to ERC20-compliant token contracts. Tokens are
+ // transferred out of the Vault by calling the `IERC20.transfer` function, and transferred in by calling
+ // `IERC20.transferFrom`. In these cases, the sender must have previously allowed the Vault to use their tokens by
+ // calling `IERC20.approve`. The only deviation from the ERC20 standard that is supported is functions not returning
+ // a boolean value: in these scenarios, a non-reverting call is assumed to be successful.
+ //
+ // - All non-view functions in the Vault are non-reentrant: calling them while another one is mid-execution (e.g.
+ // while execution control is transferred to a token contract during a swap) will result in a revert. View
+ // functions can be called in a re-reentrant way, but doing so might cause them to return inconsistent results.
+ // Contracts calling view functions in the Vault must make sure the Vault has not already been entered.
+ //
+ // - View functions revert if referring to either unregistered Pools, or unregistered tokens for registered Pools.
+
+ // Authorizer
+ //
+ // Some system actions are permissioned, like setting and collecting protocol fees. This permissioning system exists
+ // outside of the Vault in the Authorizer contract: the Vault simply calls the Authorizer to check if the caller
+ // can perform a given action.
+
+ /**
+ * @dev Returns the Vault's Authorizer.
+ */
+ function getAuthorizer() external view returns (IAuthorizer);
+
+ /**
+ * @dev Sets a new Authorizer for the Vault. The caller must be allowed by the current Authorizer to do this.
+ *
+ * Emits an `AuthorizerChanged` event.
+ */
+ function setAuthorizer(IAuthorizer newAuthorizer) external;
+
+ /**
+ * @dev Emitted when a new authorizer is set by `setAuthorizer`.
+ */
+ event AuthorizerChanged(IAuthorizer indexed newAuthorizer);
+
+ // Relayers
+ //
+ // Additionally, it is possible for an account to perform certain actions on behalf of another one, using their
+ // Vault ERC20 allowance and Internal Balance. These accounts are said to be 'relayers' for these Vault functions,
+ // and are expected to be smart contracts with sound authentication mechanisms. For an account to be able to wield
+ // this power, two things must occur:
+ // - The Authorizer must grant the account the permission to be a relayer for the relevant Vault function. This
+ // means that Balancer governance must approve each individual contract to act as a relayer for the intended
+ // functions.
+ // - Each user must approve the relayer to act on their behalf.
+ // This double protection means users cannot be tricked into approving malicious relayers (because they will not
+ // have been allowed by the Authorizer via governance), nor can malicious relayers approved by a compromised
+ // Authorizer or governance drain user funds, since they would also need to be approved by each individual user.
+
+ /**
+ * @dev Returns true if `user` has approved `relayer` to act as a relayer for them.
+ */
+ function hasApprovedRelayer(address user, address relayer) external view returns (bool);
+
+ /**
+ * @dev Allows `relayer` to act as a relayer for `sender` if `approved` is true, and disallows it otherwise.
+ *
+ * Emits a `RelayerApprovalChanged` event.
+ */
+ function setRelayerApproval(
+ address sender,
+ address relayer,
+ bool approved
+ ) external;
+
+ /**
+ * @dev Emitted every time a relayer is approved or disapproved by `setRelayerApproval`.
+ */
+ event RelayerApprovalChanged(address indexed relayer, address indexed sender, bool approved);
+
+ // Internal Balance
+ //
+ // Users can deposit tokens into the Vault, where they are allocated to their Internal Balance, and later
+ // transferred or withdrawn. It can also be used as a source of tokens when joining Pools, as a destination
+ // when exiting them, and as either when performing swaps. This usage of Internal Balance results in greatly reduced
+ // gas costs when compared to relying on plain ERC20 transfers, leading to large savings for frequent users.
+ //
+ // Internal Balance management features batching, which means a single contract call can be used to perform multiple
+ // operations of different kinds, with different senders and recipients, at once.
+
+ /**
+ * @dev Returns `user`'s Internal Balance for a set of tokens.
+ */
+ function getInternalBalance(address user, IERC20[] memory tokens) external view returns (uint256[] memory);
+
+ /**
+ * @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer)
+ * and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as
+ * it lets integrators reuse a user's Vault allowance.
+ *
+ * For each operation, if the caller is not `sender`, it must be an authorized relayer for them.
+ */
+ function manageUserBalance(UserBalanceOp[] memory ops) external payable;
+
+ /**
+ * @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received
+ without manual WETH wrapping or unwrapping.
+ */
+ struct UserBalanceOp {
+ UserBalanceOpKind kind;
+ IAsset asset;
+ uint256 amount;
+ address sender;
+ address payable recipient;
+ }
+
+ // There are four possible operations in `manageUserBalance`:
+ //
+ // - DEPOSIT_INTERNAL
+ // Increases the Internal Balance of the `recipient` account by transferring tokens from the corresponding
+ // `sender`. The sender must have allowed the Vault to use their tokens via `IERC20.approve()`.
+ //
+ // ETH can be used by passing the ETH sentinel value as the asset and forwarding ETH in the call: it will be wrapped
+ // and deposited as WETH. Any ETH amount remaining will be sent back to the caller (not the sender, which is
+ // relevant for relayers).
+ //
+ // Emits an `InternalBalanceChanged` event.
+ //
+ //
+ // - WITHDRAW_INTERNAL
+ // Decreases the Internal Balance of the `sender` account by transferring tokens to the `recipient`.
+ //
+ // ETH can be used by passing the ETH sentinel value as the asset. This will deduct WETH instead, unwrap it and send
+ // it to the recipient as ETH.
+ //
+ // Emits an `InternalBalanceChanged` event.
+ //
+ //
+ // - TRANSFER_INTERNAL
+ // Transfers tokens from the Internal Balance of the `sender` account to the Internal Balance of `recipient`.
+ //
+ // Reverts if the ETH sentinel value is passed.
+ //
+ // Emits an `InternalBalanceChanged` event.
+ //
+ //
+ // - TRANSFER_EXTERNAL
+ // Transfers tokens from `sender` to `recipient`, using the Vault's ERC20 allowance. This is typically used by
+ // relayers, as it lets them reuse a user's Vault allowance.
+ //
+ // Reverts if the ETH sentinel value is passed.
+ //
+ // Emits an `ExternalBalanceTransfer` event.
+
+ enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL }
+
+ /**
+ * @dev Emitted when a user's Internal Balance changes, either from calls to `manageUserBalance`, or through
+ * interacting with Pools using Internal Balance.
+ *
+ * Because Internal Balance works exclusively with ERC20 tokens, ETH deposits and withdrawals will use the WETH
+ * address.
+ */
+ event InternalBalanceChanged(address indexed user, IERC20 indexed token, int256 delta);
+
+ /**
+ * @dev Emitted when a user's Vault ERC20 allowance is used by the Vault to transfer tokens to an external account.
+ */
+ event ExternalBalanceTransfer(IERC20 indexed token, address indexed sender, address recipient, uint256 amount);
+
+ // Pools
+ //
+ // There are three specialization settings for Pools, which allow for cheaper swaps at the cost of reduced
+ // functionality:
+ //
+ // - General: no specialization, suited for all Pools. IGeneralPool is used for swap request callbacks, passing the
+ // balance of all tokens in the Pool. These Pools have the largest swap costs (because of the extra storage reads),
+ // which increase with the number of registered tokens.
+ //
+ // - Minimal Swap Info: IMinimalSwapInfoPool is used instead of IGeneralPool, which saves gas by only passing the
+ // balance of the two tokens involved in the swap. This is suitable for some pricing algorithms, like the weighted
+ // constant product one popularized by Balancer V1. Swap costs are smaller compared to general Pools, and are
+ // independent of the number of registered tokens.
+ //
+ // - Two Token: only allows two tokens to be registered. This achieves the lowest possible swap gas cost. Like
+ // minimal swap info Pools, these are called via IMinimalSwapInfoPool.
+
+ enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN }
+
+ /**
+ * @dev Registers the caller account as a Pool with a given specialization setting. Returns the Pool's ID, which
+ * is used in all Pool-related functions. Pools cannot be deregistered, nor can the Pool's specialization be
+ * changed.
+ *
+ * The caller is expected to be a smart contract that implements either `IGeneralPool` or `IMinimalSwapInfoPool`,
+ * depending on the chosen specialization setting. This contract is known as the Pool's contract.
+ *
+ * Note that the same contract may register itself as multiple Pools with unique Pool IDs, or in other words,
+ * multiple Pools may share the same contract.
+ *
+ * Emits a `PoolRegistered` event.
+ */
+ function registerPool(PoolSpecialization specialization) external returns (bytes32);
+
+ /**
+ * @dev Emitted when a Pool is registered by calling `registerPool`.
+ */
+ event PoolRegistered(bytes32 indexed poolId, address indexed poolAddress, PoolSpecialization specialization);
+
+ /**
+ * @dev Returns a Pool's contract address and specialization setting.
+ */
+ function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);
+
+ /**
+ * @dev Registers `tokens` for the `poolId` Pool. Must be called by the Pool's contract.
+ *
+ * Pools can only interact with tokens they have registered. Users join a Pool by transferring registered tokens,
+ * exit by receiving registered tokens, and can only swap registered tokens.
+ *
+ * Each token can only be registered once. For Pools with the Two Token specialization, `tokens` must have a length
+ * of two, that is, both tokens must be registered in the same `registerTokens` call, and they must be sorted in
+ * ascending order.
+ *
+ * The `tokens` and `assetManagers` arrays must have the same length, and each entry in these indicates the Asset
+ * Manager for the corresponding token. Asset Managers can manage a Pool's tokens via `managePoolBalance`,
+ * depositing and withdrawing them directly, and can even set their balance to arbitrary amounts. They are therefore
+ * expected to be highly secured smart contracts with sound design principles, and the decision to register an
+ * Asset Manager should not be made lightly.
+ *
+ * Pools can choose not to assign an Asset Manager to a given token by passing in the zero address. Once an Asset
+ * Manager is set, it cannot be changed except by deregistering the associated token and registering again with a
+ * different Asset Manager.
+ *
+ * Emits a `TokensRegistered` event.
+ */
+ function registerTokens(
+ bytes32 poolId,
+ IERC20[] memory tokens,
+ address[] memory assetManagers
+ ) external;
+
+ /**
+ * @dev Emitted when a Pool registers tokens by calling `registerTokens`.
+ */
+ event TokensRegistered(bytes32 indexed poolId, IERC20[] tokens, address[] assetManagers);
+
+ /**
+ * @dev Deregisters `tokens` for the `poolId` Pool. Must be called by the Pool's contract.
+ *
+ * Only registered tokens (via `registerTokens`) can be deregistered. Additionally, they must have zero total
+ * balance. For Pools with the Two Token specialization, `tokens` must have a length of two, that is, both tokens
+ * must be deregistered in the same `deregisterTokens` call.
+ *
+ * A deregistered token can be re-registered later on, possibly with a different Asset Manager.
+ *
+ * Emits a `TokensDeregistered` event.
+ */
+ function deregisterTokens(bytes32 poolId, IERC20[] memory tokens) external;
+
+ /**
+ * @dev Emitted when a Pool deregisters tokens by calling `deregisterTokens`.
+ */
+ event TokensDeregistered(bytes32 indexed poolId, IERC20[] tokens);
+
+ /**
+ * @dev Returns detailed information for a Pool's registered token.
+ *
+ * `cash` is the number of tokens the Vault currently holds for the Pool. `managed` is the number of tokens
+ * withdrawn and held outside the Vault by the Pool's token Asset Manager. The Pool's total balance for `token`
+ * equals the sum of `cash` and `managed`.
+ *
+ * Internally, `cash` and `managed` are stored using 112 bits. No action can ever cause a Pool's token `cash`,
+ * `managed` or `total` balance to be greater than 2^112 - 1.
+ *
+ * `lastChangeBlock` is the number of the block in which `token`'s total balance was last modified (via either a
+ * join, exit, swap, or Asset Manager update). This value is useful to avoid so-called 'sandwich attacks', for
+ * example when developing price oracles. A change of zero (e.g. caused by a swap with amount zero) is considered a
+ * change for this purpose, and will update `lastChangeBlock`.
+ *
+ * `assetManager` is the Pool's token Asset Manager.
+ */
+ function getPoolTokenInfo(bytes32 poolId, IERC20 token)
+ external
+ view
+ returns (
+ uint256 cash,
+ uint256 managed,
+ uint256 lastChangeBlock,
+ address assetManager
+ );
+
+ /**
+ * @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of
+ * the tokens' `balances` changed.
+ *
+ * The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all
+ * Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order.
+ *
+ * If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same
+ * order as passed to `registerTokens`.
+ *
+ * Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are
+ * the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo`
+ * instead.
+ */
+ function getPoolTokens(bytes32 poolId)
+ external
+ view
+ returns (
+ IERC20[] memory tokens,
+ uint256[] memory balances,
+ uint256 lastChangeBlock
+ );
+
+ /**
+ * @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will
+ * trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized
+ * Pool shares.
+ *
+ * If the caller is not `sender`, it must be an authorized relayer for them.
+ *
+ * The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount
+ * to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces
+ * these maximums.
+ *
+ * If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable
+ * this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the
+ * WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent
+ * back to the caller (not the sender, which is important for relayers).
+ *
+ * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when
+ * interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be
+ * sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final
+ * `assets` array might not be sorted. Pools with no registered tokens cannot be joined.
+ *
+ * If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only
+ * be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be
+ * withdrawn from Internal Balance: attempting to do so will trigger a revert.
+ *
+ * This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement
+ * their own custom logic. This typically requires additional information from the user (such as the expected number
+ * of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed
+ * directly to the Pool's contract, as is `recipient`.
+ *
+ * Emits a `PoolBalanceChanged` event.
+ */
+ function joinPool(
+ bytes32 poolId,
+ address sender,
+ address recipient,
+ JoinPoolRequest memory request
+ ) external payable;
+
+ struct JoinPoolRequest {
+ IAsset[] assets;
+ uint256[] maxAmountsIn;
+ bytes userData;
+ bool fromInternalBalance;
+ }
+
+ /**
+ * @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will
+ * trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized
+ * Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see
+ * `getPoolTokenInfo`).
+ *
+ * If the caller is not `sender`, it must be an authorized relayer for them.
+ *
+ * The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum
+ * token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault:
+ * it just enforces these minimums.
+ *
+ * If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To
+ * enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead
+ * of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit.
+ *
+ * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when
+ * interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must
+ * be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the
+ * final `assets` array might not be sorted. Pools with no registered tokens cannot be exited.
+ *
+ * If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise,
+ * an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to
+ * do so will trigger a revert.
+ *
+ * `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the
+ * `tokens` array. This array must match the Pool's registered tokens.
+ *
+ * This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement
+ * their own custom logic. This typically requires additional information from the user (such as the expected number
+ * of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and
+ * passed directly to the Pool's contract.
+ *
+ * Emits a `PoolBalanceChanged` event.
+ */
+ function exitPool(
+ bytes32 poolId,
+ address sender,
+ address payable recipient,
+ ExitPoolRequest memory request
+ ) external;
+
+ struct ExitPoolRequest {
+ IAsset[] assets;
+ uint256[] minAmountsOut;
+ bytes userData;
+ bool toInternalBalance;
+ }
+
+ /**
+ * @dev Emitted when a user joins or exits a Pool by calling `joinPool` or `exitPool`, respectively.
+ */
+ event PoolBalanceChanged(
+ bytes32 indexed poolId,
+ address indexed liquidityProvider,
+ IERC20[] tokens,
+ int256[] deltas,
+ uint256[] protocolFeeAmounts
+ );
+
+ enum PoolBalanceChangeKind { JOIN, EXIT }
+
+ // Swaps
+ //
+ // Users can swap tokens with Pools by calling the `swap` and `batchSwap` functions. To do this,
+ // they need not trust Pool contracts in any way: all security checks are made by the Vault. They must however be
+ // aware of the Pools' pricing algorithms in order to estimate the prices Pools will quote.
+ //
+ // The `swap` function executes a single swap, while `batchSwap` can perform multiple swaps in sequence.
+ // In each individual swap, tokens of one kind are sent from the sender to the Pool (this is the 'token in'),
+ // and tokens of another kind are sent from the Pool to the recipient in exchange (this is the 'token out').
+ // More complex swaps, such as one token in to multiple tokens out can be achieved by batching together
+ // individual swaps.
+ //
+ // There are two swap kinds:
+ // - 'given in' swaps, where the amount of tokens in (sent to the Pool) is known, and the Pool determines (via the
+ // `onSwap` hook) the amount of tokens out (to send to the recipient).
+ // - 'given out' swaps, where the amount of tokens out (received from the Pool) is known, and the Pool determines
+ // (via the `onSwap` hook) the amount of tokens in (to receive from the sender).
+ //
+ // Additionally, it is possible to chain swaps using a placeholder input amount, which the Vault replaces with
+ // the calculated output of the previous swap. If the previous swap was 'given in', this will be the calculated
+ // tokenOut amount. If the previous swap was 'given out', it will use the calculated tokenIn amount. These extended
+ // swaps are known as 'multihop' swaps, since they 'hop' through a number of intermediate tokens before arriving at
+ // the final intended token.
+ //
+ // In all cases, tokens are only transferred in and out of the Vault (or withdrawn from and deposited into Internal
+ // Balance) after all individual swaps have been completed, and the net token balance change computed. This makes
+ // certain swap patterns, such as multihops, or swaps that interact with the same token pair in multiple Pools, cost
+ // much less gas than they would otherwise.
+ //
+ // It also means that under certain conditions it is possible to perform arbitrage by swapping with multiple
+ // Pools in a way that results in net token movement out of the Vault (profit), with no tokens being sent in (only
+ // updating the Pool's internal accounting).
+ //
+ // To protect users from front-running or the market changing rapidly, they supply a list of 'limits' for each token
+ // involved in the swap, where either the maximum number of tokens to send (by passing a positive value) or the
+ // minimum amount of tokens to receive (by passing a negative value) is specified.
+ //
+ // Additionally, a 'deadline' timestamp can also be provided, forcing the swap to fail if it occurs after
+ // this point in time (e.g. if the transaction failed to be included in a block promptly).
+ //
+ // If interacting with Pools that hold WETH, it is possible to both send and receive ETH directly: the Vault will do
+ // the wrapping and unwrapping. To enable this mechanism, the IAsset sentinel value (the zero address) must be
+ // passed in the `assets` array instead of the WETH address. Note that it is possible to combine ETH and WETH in the
+ // same swap. Any excess ETH will be sent back to the caller (not the sender, which is relevant for relayers).
+ //
+ // Finally, Internal Balance can be used when either sending or receiving tokens.
+
+ enum SwapKind { GIVEN_IN, GIVEN_OUT }
+
+ /**
+ * @dev Performs a swap with a single Pool.
+ *
+ * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens
+ * taken from the Pool, which must be greater than or equal to `limit`.
+ *
+ * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens
+ * sent to the Pool, which must be less than or equal to `limit`.
+ *
+ * Internal Balance usage and the recipient are determined by the `funds` struct.
+ *
+ * Emits a `Swap` event.
+ */
+ function swap(
+ SingleSwap memory singleSwap,
+ FundManagement memory funds,
+ uint256 limit,
+ uint256 deadline
+ ) external payable returns (uint256);
+
+ /**
+ * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on
+ * the `kind` value.
+ *
+ * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address).
+ * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault.
+ *
+ * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
+ * used to extend swap behavior.
+ */
+ struct SingleSwap {
+ bytes32 poolId;
+ SwapKind kind;
+ IAsset assetIn;
+ IAsset assetOut;
+ uint256 amount;
+ bytes userData;
+ }
+
+ /**
+ * @dev Performs a series of swaps with one or multiple Pools. In each individual swap, the caller determines either
+ * the amount of tokens sent to or received from the Pool, depending on the `kind` value.
+ *
+ * Returns an array with the net Vault asset balance deltas. Positive amounts represent tokens (or ETH) sent to the
+ * Vault, and negative amounts represent tokens (or ETH) sent by the Vault. Each delta corresponds to the asset at
+ * the same index in the `assets` array.
+ *
+ * Swaps are executed sequentially, in the order specified by the `swaps` array. Each array element describes a
+ * Pool, the token to be sent to this Pool, the token to receive from it, and an amount that is either `amountIn` or
+ * `amountOut` depending on the swap kind.
+ *
+ * Multihop swaps can be executed by passing an `amount` value of zero for a swap. This will cause the amount in/out
+ * of the previous swap to be used as the amount in for the current one. In a 'given in' swap, 'tokenIn' must equal
+ * the previous swap's `tokenOut`. For a 'given out' swap, `tokenOut` must equal the previous swap's `tokenIn`.
+ *
+ * The `assets` array contains the addresses of all assets involved in the swaps. These are either token addresses,
+ * or the IAsset sentinel value for ETH (the zero address). Each entry in the `swaps` array specifies tokens in and
+ * out by referencing an index in `assets`. Note that Pools never interact with ETH directly: it will be wrapped to
+ * or unwrapped from WETH by the Vault.
+ *
+ * Internal Balance usage, sender, and recipient are determined by the `funds` struct. The `limits` array specifies
+ * the minimum or maximum amount of each token the vault is allowed to transfer.
+ *
+ * `batchSwap` can be used to make a single swap, like `swap` does, but doing so requires more gas than the
+ * equivalent `swap` call.
+ *
+ * Emits `Swap` events.
+ */
+ function batchSwap(
+ SwapKind kind,
+ BatchSwapStep[] memory swaps,
+ IAsset[] memory assets,
+ FundManagement memory funds,
+ int256[] memory limits,
+ uint256 deadline
+ ) external payable returns (int256[] memory);
+
+ /**
+ * @dev Data for each individual swap executed by `batchSwap`. The asset in and out fields are indexes into the
+ * `assets` array passed to that function, and ETH assets are converted to WETH.
+ *
+ * If `amount` is zero, the multihop mechanism is used to determine the actual amount based on the amount in/out
+ * from the previous swap, depending on the swap kind.
+ *
+ * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
+ * used to extend swap behavior.
+ */
+ struct BatchSwapStep {
+ bytes32 poolId;
+ uint256 assetInIndex;
+ uint256 assetOutIndex;
+ uint256 amount;
+ bytes userData;
+ }
+
+ /**
+ * @dev Emitted for each individual swap performed by `swap` or `batchSwap`.
+ */
+ event Swap(
+ bytes32 indexed poolId,
+ IERC20 indexed tokenIn,
+ IERC20 indexed tokenOut,
+ uint256 amountIn,
+ uint256 amountOut
+ );
+
+ /**
+ * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the
+ * `recipient` account.
+ *
+ * If the caller is not `sender`, it must be an authorized relayer for them.
+ *
+ * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20
+ * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender`
+ * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of
+ * `joinPool`.
+ *
+ * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of
+ * transferred. This matches the behavior of `exitPool`.
+ *
+ * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a
+ * revert.
+ */
+ struct FundManagement {
+ address sender;
+ bool fromInternalBalance;
+ address payable recipient;
+ bool toInternalBalance;
+ }
+
+ /**
+ * @dev Simulates a call to `batchSwap`, returning an array of Vault asset deltas. Calls to `swap` cannot be
+ * simulated directly, but an equivalent `batchSwap` call can and will yield the exact same result.
+ *
+ * Each element in the array corresponds to the asset at the same index, and indicates the number of tokens (or ETH)
+ * the Vault would take from the sender (if positive) or send to the recipient (if negative). The arguments it
+ * receives are the same that an equivalent `batchSwap` call would receive.
+ *
+ * Unlike `batchSwap`, this function performs no checks on the sender or recipient field in the `funds` struct.
+ * This makes it suitable to be called by off-chain applications via eth_call without needing to hold tokens,
+ * approve them for the Vault, or even know a user's address.
+ *
+ * Note that this function is not 'view' (due to implementation details): the client code must explicitly execute
+ * eth_call instead of eth_sendTransaction.
+ */
+ function queryBatchSwap(
+ SwapKind kind,
+ BatchSwapStep[] memory swaps,
+ IAsset[] memory assets,
+ FundManagement memory funds
+ ) external returns (int256[] memory assetDeltas);
+
+ // Flash Loans
+
+ /**
+ * @dev Performs a 'flash loan', sending tokens to `recipient`, executing the `receiveFlashLoan` hook on it,
+ * and then reverting unless the tokens plus a proportional protocol fee have been returned.
+ *
+ * The `tokens` and `amounts` arrays must have the same length, and each entry in these indicates the loan amount
+ * for each token contract. `tokens` must be sorted in ascending order.
+ *
+ * The 'userData' field is ignored by the Vault, and forwarded as-is to `recipient` as part of the
+ * `receiveFlashLoan` call.
+ *
+ * Emits `FlashLoan` events.
+ */
+ function flashLoan(
+ IFlashLoanRecipient recipient,
+ IERC20[] memory tokens,
+ uint256[] memory amounts,
+ bytes memory userData
+ ) external;
+
+ /**
+ * @dev Emitted for each individual flash loan performed by `flashLoan`.
+ */
+ event FlashLoan(IFlashLoanRecipient indexed recipient, IERC20 indexed token, uint256 amount, uint256 feeAmount);
+
+ // Asset Management
+ //
+ // Each token registered for a Pool can be assigned an Asset Manager, which is able to freely withdraw the Pool's
+ // tokens from the Vault, deposit them, or assign arbitrary values to its `managed` balance (see
+ // `getPoolTokenInfo`). This makes them extremely powerful and dangerous. Even if an Asset Manager only directly
+ // controls one of the tokens in a Pool, a malicious manager could set that token's balance to manipulate the
+ // prices of the other tokens, and then drain the Pool with swaps. The risk of using Asset Managers is therefore
+ // not constrained to the tokens they are managing, but extends to the entire Pool's holdings.
+ //
+ // However, a properly designed Asset Manager smart contract can be safely used for the Pool's benefit,
+ // for example by lending unused tokens out for interest, or using them to participate in voting protocols.
+ //
+ // This concept is unrelated to the IAsset interface.
+
+ /**
+ * @dev Performs a set of Pool balance operations, which may be either withdrawals, deposits or updates.
+ *
+ * Pool Balance management features batching, which means a single contract call can be used to perform multiple
+ * operations of different kinds, with different Pools and tokens, at once.
+ *
+ * For each operation, the caller must be registered as the Asset Manager for `token` in `poolId`.
+ */
+ function managePoolBalance(PoolBalanceOp[] memory ops) external;
+
+ struct PoolBalanceOp {
+ PoolBalanceOpKind kind;
+ bytes32 poolId;
+ IERC20 token;
+ uint256 amount;
+ }
+
+ /**
+ * Withdrawals decrease the Pool's cash, but increase its managed balance, leaving the total balance unchanged.
+ *
+ * Deposits increase the Pool's cash, but decrease its managed balance, leaving the total balance unchanged.
+ *
+ * Updates don't affect the Pool's cash balance, but because the managed balance changes, it does alter the total.
+ * The external amount can be either increased or decreased by this call (i.e., reporting a gain or a loss).
+ */
+ enum PoolBalanceOpKind { WITHDRAW, DEPOSIT, UPDATE }
+
+ /**
+ * @dev Emitted when a Pool's token Asset Manager alters its balance via `managePoolBalance`.
+ */
+ event PoolBalanceManaged(
+ bytes32 indexed poolId,
+ address indexed assetManager,
+ IERC20 indexed token,
+ int256 cashDelta,
+ int256 managedDelta
+ );
+
+ // Protocol Fees
+ //
+ // Some operations cause the Vault to collect tokens in the form of protocol fees, which can then be withdrawn by
+ // permissioned accounts.
+ //
+ // There are two kinds of protocol fees:
+ //
+ // - flash loan fees: charged on all flash loans, as a percentage of the amounts lent.
+ //
+ // - swap fees: a percentage of the fees charged by Pools when performing swaps. For a number of reasons, including
+ // swap gas costs and interface simplicity, protocol swap fees are not charged on each individual swap. Rather,
+ // Pools are expected to keep track of how much they have charged in swap fees, and pay any outstanding debts to the
+ // Vault when they are joined or exited. This prevents users from joining a Pool with unpaid debt, as well as
+ // exiting a Pool in debt without first paying their share.
+
+ /**
+ * @dev Returns the current protocol fee module.
+ */
+ function getProtocolFeesCollector() external view returns (IProtocolFeesCollector);
+
+ /**
+ * @dev Safety mechanism to pause most Vault operations in the event of an emergency - typically detection of an
+ * error in some part of the system.
+ *
+ * The Vault can only be paused during an initial time period, after which pausing is forever disabled.
+ *
+ * While the contract is paused, the following features are disabled:
+ * - depositing and transferring internal balance
+ * - transferring external balance (using the Vault's allowance)
+ * - swaps
+ * - joining Pools
+ * - Asset Manager interactions
+ *
+ * Internal Balance can still be withdrawn, and Pools exited.
+ */
+ function setPaused(bool paused) external;
+
+ /**
+ * @dev Returns the Vault's WETH instance.
+ */
+ function WETH() external view returns (IWETH);
+ // solhint-disable-previous-line func-name-mixedcase
+}
diff --git a/foundry/lib/balancer-labs/v2-interfaces/package.json b/foundry/lib/balancer-labs/v2-interfaces/package.json
new file mode 100644
index 0000000..1608cae
--- /dev/null
+++ b/foundry/lib/balancer-labs/v2-interfaces/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "@balancer-labs/v2-interfaces",
+ "version": "0.4.0",
+ "description": "V2 Interfaces",
+ "license": "GPL-3.0-only",
+ "homepage": "https://github.com/balancer-labs/balancer-v2-monorepo/tree/master/pkg/interfaces#readme",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/balancer-labs/balancer-v2-monorepo.git",
+ "directory": "pkg/interfaces"
+ },
+ "bugs": {
+ "url": "https://github.com/balancer-labs/balancer-v2-monorepo/issues"
+ },
+ "files": [
+ "contracts/**/*"
+ ],
+ "scripts": {
+ "build": "yarn compile",
+ "compile": "hardhat compile && rm -rf artifacts/build-info",
+ "compile:watch": "nodemon --ext sol --exec yarn compile",
+ "lint": "yarn lint:solidity && yarn lint:typescript",
+ "lint:solidity": "solhint 'contracts/**/*.sol'",
+ "lint:typescript": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ../../.eslintignore --max-warnings 0"
+ },
+ "devDependencies": {
+ "@nomiclabs/hardhat-ethers": "^2.2.1",
+ "@nomiclabs/hardhat-waffle": "^2.0.3",
+ "@types/chai": "^4.3.3",
+ "@types/lodash": "^4.14.186",
+ "@types/mocha": "^10.0.0",
+ "@types/node": "^14.14.31",
+ "@typescript-eslint/eslint-plugin": "^5.41.0",
+ "@typescript-eslint/parser": "^5.41.0",
+ "chai": "^4.3.6",
+ "decimal.js": "^10.4.2",
+ "eslint": "^8.26.0",
+ "eslint-plugin-mocha-no-only": "^1.1.1",
+ "eslint-plugin-prettier": "^4.2.1",
+ "ethereum-waffle": "^3.4.4",
+ "ethers": "^5.7.2",
+ "hardhat": "^2.12.5",
+ "hardhat-ignore-warnings": "^0.2.4",
+ "lodash.frompairs": "^4.0.1",
+ "lodash.pick": "^4.4.0",
+ "lodash.range": "^3.2.0",
+ "lodash.times": "^4.3.2",
+ "lodash.zip": "^4.2.0",
+ "mocha": "^10.1.0",
+ "nodemon": "^2.0.20",
+ "prettier": "^2.7.1",
+ "prettier-plugin-solidity": "v1.0.0-alpha.59",
+ "solhint": "^3.2.0",
+ "solhint-plugin-prettier": "^0.0.4",
+ "ts-node": "^10.9.1",
+ "typescript": "^4.0.2"
+ }
+}
\ No newline at end of file
diff --git a/foundry/remappings.txt b/foundry/remappings.txt
index f4b9a08..6d33fc1 100644
--- a/foundry/remappings.txt
+++ b/foundry/remappings.txt
@@ -2,4 +2,5 @@
@interfaces/=interfaces/
@permit2/=lib/permit2/
@src/=src/
-@uniswap-v2/=lib/v2-core/
\ No newline at end of file
+@uniswap-v2/=lib/v2-core/
+@balancer-labs/v2-interfaces/=lib/balancer-labs/v2-interfaces/
\ No newline at end of file
diff --git a/foundry/src/executors/BalancerV2Executor.sol b/foundry/src/executors/BalancerV2Executor.sol
new file mode 100644
index 0000000..10b2826
--- /dev/null
+++ b/foundry/src/executors/BalancerV2Executor.sol
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.28;
+
+import "@interfaces/IExecutor.sol";
+import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+import "@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol";
+import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
+
+
+error BalancerV2Executor__InvalidDataLength();
+
+contract BalancerV2Executor is IExecutor {
+ using SafeERC20 for IERC20;
+
+ address private constant VAULT = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;
+
+ function swap(uint256 givenAmount, bytes calldata data)
+ external
+ returns (uint256 calculatedAmount)
+ {
+
+ (
+ IERC20 tokenIn,
+ IERC20 tokenOut,
+ bytes32 poolId,
+ address receiver,
+ bool exactOut,
+ bool needsApproval
+ ) = _decodeData(data);
+
+
+ if (needsApproval) {
+ tokenIn.safeApprove(VAULT, type(uint256).max);
+ }
+
+
+ IVault.SingleSwap memory singleSwap = IVault.SingleSwap({
+ poolId: poolId,
+ kind: exactOut ? IVault.SwapKind.GIVEN_OUT : IVault.SwapKind.GIVEN_IN,
+ assetIn: IAsset(address(tokenIn)),
+ assetOut: IAsset(address(tokenOut)),
+ amount: givenAmount,
+ userData: ""
+ });
+
+
+ IVault.FundManagement memory funds = IVault.FundManagement({
+ sender: address(this),
+ fromInternalBalance: false,
+ recipient: payable(receiver),
+ toInternalBalance: false
+ });
+
+
+ uint256 limit = exactOut ? type(uint256).max : 0;
+
+
+ calculatedAmount = IVault(VAULT).swap(
+ singleSwap,
+ funds,
+ limit,
+ block.timestamp
+ );
+ }
+
+ function _decodeData(bytes calldata data)
+ internal
+ pure
+ returns (
+ IERC20 tokenIn,
+ IERC20 tokenOut,
+ bytes32 poolId,
+ address receiver,
+ bool exactOut,
+ bool needsApproval
+ )
+ {
+ // Verify data length (20 + 20 + 32 + 20 + 1 + 1 = 94 bytes)
+ if (data.length != 94) {
+ revert BalancerV2Executor__InvalidDataLength();
+ }
+
+
+ tokenIn = IERC20(address(bytes20(data[0:20])));
+ tokenOut = IERC20(address(bytes20(data[20:40])));
+ poolId = bytes32(data[40:72]);
+ receiver = address(bytes20(data[72:92]));
+ exactOut = uint8(data[92]) > 0;
+ needsApproval = uint8(data[93]) > 0;
+ }
+}
\ No newline at end of file