From c5e8d89a183313c19388c3dcfbf652d6f740578e Mon Sep 17 00:00:00 2001 From: Jeff Bennett Date: Mon, 25 Nov 2024 19:20:39 -0500 Subject: [PATCH 1/3] Cumulative update, mostly of buffer functionality, such as adding limits (and a new Router). Also adds disabling queries permanently. --- docs/concepts/core-concepts/architecture.md | 2 +- docs/concepts/router/overview.md | 5 + docs/concepts/router/queries.md | 7 + docs/concepts/vault/buffer.md | 32 ++-- docs/concepts/vault/erc20-multi-token.md | 8 +- .../contracts/abi/README.md | 1 + .../contracts/abi/buffer-router.md | 9 ++ .../contracts/buffer-router-api.md | 148 ++++++++++++++++++ .../composite-liquidity-router-api.md | 14 ++ .../contracts/deployment-addresses/sepolia.md | 33 ++-- .../contracts/error-codes.md | 5 +- .../contracts/protocol-fee-controller-api.md | 15 ++ .../contracts/router-api.md | 79 +++------- .../contracts/vault-api.md | 130 +++++++++++++-- .../aggregators/useful-resources.md | 2 + 15 files changed, 391 insertions(+), 99 deletions(-) create mode 100644 docs/developer-reference/contracts/abi/buffer-router.md create mode 100644 docs/developer-reference/contracts/buffer-router-api.md diff --git a/docs/concepts/core-concepts/architecture.md b/docs/concepts/core-concepts/architecture.md index 6b9ea51..e6d6ca7 100644 --- a/docs/concepts/core-concepts/architecture.md +++ b/docs/concepts/core-concepts/architecture.md @@ -9,7 +9,7 @@ order: 1 The Balancer protocol architecture comprises three primary components, each strategically designed to enhance flexibility and minimize the intricacies involved in constructing pools. By distributing responsibilities across these components, Balancer simplifies pool development, empowering builders to focus on innovation rather than grappling with complex code. -- Router: Serves as the user's gateway to the protocol, offering straightforward interfaces for executing operations. (This includes the basic Router, BatchRouter, and CompositeLiquidityRouter.) +- Router: Serves as the user's gateway to the protocol, offering straightforward interfaces for executing operations. (This includes the basic Router, BatchRouter, BufferRouter, and CompositeLiquidityRouter.) - Vault: Centralizes liquidity operations and manages accounting, streamlining the handling of token balances across multiple pools. - Pool: Exposes precise pool mathematics through invariant calculations, enabling developers to harness powerful functionalities without delving into intricate details. diff --git a/docs/concepts/router/overview.md b/docs/concepts/router/overview.md index ca20850..e6298ca 100644 --- a/docs/concepts/router/overview.md +++ b/docs/concepts/router/overview.md @@ -31,6 +31,11 @@ Balancer has developed, audited and deployed Router contracts with the goal of p - [API](../../developer-reference/contracts/batch-router-api.md) - [Code](https://github.com/balancer/balancer-v3-monorepo/blob/main/pkg/vault/contracts/BatchRouter.sol) +### Buffer Router +- Liquidity operations on buffers +- [API](../../developer-reference/contracts/buffer-router-api.md) +- [Code](https://github.com/balancer/balancer-v3-monorepo/blob/main/pkg/vault/contracts/BufferRouter.sol) + ### Composite Liquidity Router - Liquidity operations on pools containing ERC4626 tokens, and nested pools (i.e. pools containing the BPT of other pools) - [API](../../developer-reference/contracts/composite-liquidity-router-api.md) diff --git a/docs/concepts/router/queries.md b/docs/concepts/router/queries.md index 63ea290..5dc049a 100644 --- a/docs/concepts/router/queries.md +++ b/docs/concepts/router/queries.md @@ -25,6 +25,13 @@ The detailed Router API description can be found in the [Batch Router API sectio - `querySwapExactIn` - `querySwapExactOut` +## Buffer Router queries +The detailed Buffer Router API description can be found in the [Buffer Router API section](/concepts/router/onchain-api/buffer-router-api.html). + +- `queryInitializeBuffer` +- `queryAddLiquidityToBuffer` +- `queryRemoveLiquidityToBuffer` + ## Composite Liquidity Router queries The detailed Router API description can be found in the [Composite Liquidity Router API section](/concepts/router/onchain-api/composite-liquidity-router-api.html). diff --git a/docs/concepts/vault/buffer.md b/docs/concepts/vault/buffer.md index 7d8122e..d6ec509 100644 --- a/docs/concepts/vault/buffer.md +++ b/docs/concepts/vault/buffer.md @@ -24,18 +24,24 @@ If your organization is a DAO and you're seeking to enhance liquidity for your E ## Adding liquidity to a buffer -Liquidity can be added to a buffer for a specific token pair. This is done by invoking the `addLiquidityToBuffer` function, where you designate the ERC4626 Token as the buffer reference. Note that for security reasons, liquidity can only be added (or removed) proportionally. It's important to note that a buffer can still function with zero liquidity. It can be used to wrap and unwrap assets, meaning that even an empty buffer can facilitate swaps through the Vault. +Liquidity can be added to a buffer for a specific token pair. This is done by invoking the `addLiquidityToBuffer` function in the [Buffer Router](https://github.com/balancer/balancer-v3-monorepo/blob/main/pkg/vault/contracts/BufferRouter.sol), where you designate the ERC4626 Token as the buffer reference. Note that for security reasons, liquidity can only be added (or removed) proportionally. It's important to note that a buffer can still function with zero liquidity. It can be used to wrap and unwrap assets, meaning that even an empty buffer can facilitate swaps through the Vault. ```solidity /** - * @notice Adds liquidity to a yield-bearing buffer (one of the Vault's internal ERC4626 token buffers). + * @notice Adds liquidity proportionally to an internal ERC4626 buffer in the Vault. + * @dev Requires the buffer to be initialized beforehand. Restricting adds to proportional simplifies the Vault + * code, avoiding rounding issues and minimum amount checks. It is possible to add unbalanced by interacting + * with the wrapper contract directly. * @param wrappedToken Address of the wrapped token that implements IERC4626 - * @param exactSharesToIssue The value in underlying tokens that `sharesOwner` wants to add to the buffer, - * in underlying token decimals - * @return amountUnderlyingRaw Amount of underlying tokens deposited into the buffer - * @return amountWrappedRaw Amount of wrapped tokens deposited into the buffer -*/ + * @param maxAmountUnderlyingIn Maximum amount of underlying tokens to add to the buffer. It is expressed in underlying token native decimals + * @param maxAmountWrappedIn Maximum amount of wrapped tokens to add to the buffer. It is expressed in wrapped token native decimals + * @param exactSharesToIssue The amount of shares that `sharesOwner` wants to add to the buffer, in underlying token decimals + * @return amountUnderlyingIn Amount of underlying tokens deposited into the buffer + * @return amountWrappedIn Amount of wrapped tokens deposited into the buffer + */ function addLiquidityToBuffer( IERC4626 wrappedToken, + uint256 maxAmountUnderlyingIn, + uint256 maxAmountWrappedIn, uint256 exactSharesToIssue ) external returns (uint256 amountUnderlyingRaw, uint256 amountWrappedRaw); ``` @@ -60,14 +66,18 @@ In order to keep it permissionless, `removeLiquidityFromBuffer` was moved to the * - The buffer needs to have some liquidity and have its asset registered in `_bufferAssets` storage. * * @param wrappedToken Address of the wrapped token that implements IERC4626 - * @param sharesToRemove Amount of shares to remove from the buffer. Cannot be greater than sharesOwner's - * total shares. It is expressed in underlying token native decimals. + * @param sharesToRemove Amount of shares to remove from the buffer. Cannot be greater than sharesOwner's total shares. It is expressed in underlying token native decimals + * @param minAmountUnderlyingOutRaw Minimum amount of underlying tokens to receive from the buffer. It is expressed in underlying token native decimals + * @param minAmountWrappedOutRaw Minimum amount of wrapped tokens to receive from the buffer. It is expressed in + * wrapped token native decimals * @return removedUnderlyingBalanceRaw Amount of underlying tokens returned to the user * @return removedWrappedBalanceRaw Amount of wrapped tokens returned to the user -*/ + */ function removeLiquidityFromBuffer( IERC4626 wrappedToken, - uint256 sharesToRemove + uint256 sharesToRemove, + uint256 minAmountUnderlyingOutRaw, + uint256 minAmountWrappedOutRaw ) external returns (uint256 removedUnderlyingBalanceRaw, uint256 removedWrappedBalanceRaw); ``` diff --git a/docs/concepts/vault/erc20-multi-token.md b/docs/concepts/vault/erc20-multi-token.md index a86b14a..6697e15 100644 --- a/docs/concepts/vault/erc20-multi-token.md +++ b/docs/concepts/vault/erc20-multi-token.md @@ -39,9 +39,13 @@ function _approve(address token, address owner, address spender, uint256 amount) _allowances[token][owner][spender] = amount; emit Approval(token, owner, spender, amount); - // We also emit the "approve" event on the pool token to ensure full compliance with ERC20 standards. - BalancerPoolToken(token).emitApproval(owner, spender, amount); + // We also emit the "approve" event on the pool token to ensure full compliance with the ERC20 standard. + // If this function fails we keep going, as this is used in recovery mode. + // Well-behaved pools will just emit an event here, so they should never fail. + try BalancerPoolToken(pool).emitApproval(owner, spender, amount) {} catch { + // solhint-disable-previous-line no-empty-blocks + } } ``` diff --git a/docs/developer-reference/contracts/abi/README.md b/docs/developer-reference/contracts/abi/README.md index fdefc39..0306f06 100644 --- a/docs/developer-reference/contracts/abi/README.md +++ b/docs/developer-reference/contracts/abi/README.md @@ -9,5 +9,6 @@ You can find relevant Abis here: - [Router](./router.md) - [Batch Router](./batch-router.md) +- [Buffer Router](./buffer-router.md) - [Composite Liquidity Router](./composite-liquidity-router.md) diff --git a/docs/developer-reference/contracts/abi/buffer-router.md b/docs/developer-reference/contracts/abi/buffer-router.md new file mode 100644 index 0000000..a44f27a --- /dev/null +++ b/docs/developer-reference/contracts/abi/buffer-router.md @@ -0,0 +1,9 @@ +--- +order: 2 +title: Buffer Router +--- +# Buffer Router ABI + +```json + +``` diff --git a/docs/developer-reference/contracts/buffer-router-api.md b/docs/developer-reference/contracts/buffer-router-api.md new file mode 100644 index 0000000..42764c7 --- /dev/null +++ b/docs/developer-reference/contracts/buffer-router-api.md @@ -0,0 +1,148 @@ +--- +order: 0 +title: Buffer Router API +--- + +# Buffer Router API + +The Buffer Router can be used to interact with Balancer onchain for buffer operations. + +## ERC4626 Buffers + +### `initializeBuffer` + +```solidity +function initializeBuffer( + IERC4626 wrappedToken, + uint256 exactAmountUnderlyingIn, + uint256 exactAmountWrappedIn, + uint256 minIssuedShares +) external returns (uint256 issuedShares); +``` +Adds liquidity for the first time to one of the Vault's internal ERC4626 buffers. Buffer operations will revert until the buffer is initialized. + +**Parameters:** + +| Name | Type | Description | +|---|---|---| +| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | +| exactAmountUnderlyingIn | uint256 | Amount of underlying tokens that will be deposited into the buffer | +| exactAmountWrappedIn | uint256 | Amount of wrapped tokens that will be deposited into the buffer | +| minIssuedShares | uint256 | Minimum amount of shares to receive, in underlying token native decimals | +**Returns:** + +| Name | Type | Description | +|---|---|---| +| issuedShares | uint256 | The amount of tokens sharesOwner has in the buffer, denominated in underlying tokens (This is the BPT of an internal ERC4626 token buffer) | + +### `addLiquidityToBuffer` + +```solidity +function addLiquidityToBuffer( + IERC4626 wrappedToken, + uint256 maxAmountUnderlyingIn, + uint256 maxAmountWrappedIn, + uint256 exactSharesToIssue, +) external returns (uint256 amountUnderlyingRaw, uint256 amountWrappedRaw); +``` +Adds liquidity proportionally to a yield-bearing buffer (one of the Vault's internal ERC4626 token buffers). This limitation is necessary to avoid having multiple "wrap/unwrap" paths. + +**Parameters:** + +| Name | Type | Description | +|---|---|---| +| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | +| maxAmountUnderlyingIn | uint256 | Maximum amount of underlying tokens to add to the buffer. It is expressed in underlying token native decimals | +| maxAmountWrappedIn | uint256 | Maximum amount of wrapped tokens to add to the buffer. It is expressed in wrapped token native decimals | +| exactSharesToIssue | uint256 | The value in underlying tokens that `sharesOwner` wants to add to the buffer, in underlying token decimals | + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| amountUnderlyingRaw | uint256 | Amount of underlying tokens deposited into the buffer | +| amountWrappedRaw | uint256 | Amount of wrapped tokens deposited into the buffer | + +## Queries + +### `queryInitializeBuffer` + +```solidity +function initializeBuffer( + IERC4626 wrappedToken, + uint256 exactAmountUnderlyingIn, + uint256 exactAmountWrappedIn +) external returns (uint256 issuedShares); +``` +Query an `initializeBuffer` operation without actually executing it. + +**Parameters:** + +| Name | Type | Description | +|---|---|---| +| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | +| exactAmountUnderlyingIn | uint256 | Amount of underlying tokens that will be deposited into the buffer | +| exactAmountWrappedIn | uint256 | Amount of wrapped tokens that will be deposited into the buffer | + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| issuedShares | uint256 | The amount of tokens sharesOwner has in the buffer, denominated in underlying tokens (This is the BPT of an internal ERC4626 token buffer) | + +### `queryAddLiquidityToBuffer` + +```solidity +function addLiquidityToBuffer( + IERC4626 wrappedToken, + uint256 exactSharesToIssue, +) external returns (uint256 amountUnderlyingRaw, uint256 amountWrappedRaw); +``` +Query an `addLiquidityToBuffer` operation without actually executing it. + +**Parameters:** + +| Name | Type | Description | +|---|---|---| +| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | +| maxAmountUnderlyingIn | uint256 | Maximum amount of underlying tokens to add to the buffer. It is expressed in underlying token native decimals | +| maxAmountWrappedIn | uint256 | Maximum amount of wrapped tokens to add to the buffer. It is expressed in wrapped token native decimals | +| exactSharesToIssue | uint256 | The value in underlying tokens that `sharesOwner` wants to add to the buffer, in underlying token decimals | + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| amountUnderlyingRaw | uint256 | Amount of underlying tokens deposited into the buffer | +| amountWrappedRaw | uint256 | Amount of wrapped tokens deposited into the buffer | + +### `queryRemoveLiquidityFromBuffer` + +```solidity +function queryRemoveLiquidityFromBuffer( + IERC4626 wrappedToken, + uint256 exactSharesToRemove, +) external returns (uint256 removedUnderlyingBalanceOut, uint256 removedWrappedBalanceOut); +``` +Query an `removeLiquidityToBuffer` operation without actually executing it. + +**Parameters:** + +| Name | Type | Description | +|---|---|---| +| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | +| exactSharesToRemove | uint256 | The amount of shares that would be burned, in underlying token decimals | + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| removedUnderlyingBalanceOut | uint256 | Amount of underlying tokens that would be removed from the buffer | +| removedWrappedBalanceOut | uint256 | Amount of wrapped tokens that would be removed from the buffer | + + diff --git a/docs/developer-reference/contracts/composite-liquidity-router-api.md b/docs/developer-reference/contracts/composite-liquidity-router-api.md index 2d95e7d..52a3f77 100644 --- a/docs/developer-reference/contracts/composite-liquidity-router-api.md +++ b/docs/developer-reference/contracts/composite-liquidity-router-api.md @@ -108,6 +108,7 @@ function addLiquidityUnbalancedNestedPool( address[] memory tokensIn, uint256[] memory exactAmountsIn, uint256 minBptAmountOut, + bool wethIsEth, bytes memory userData ) external returns (uint256 bptAmountOut); ``` @@ -121,6 +122,7 @@ Adds liquidity unbalanced to a nested pool. A nested pool is one in which one or | tokensIn | uint256[] memory | Input token addresses, sorted by user preference. `tokensIn` array must have all tokens from child pools and all tokens that are not BPTs from the nested pool (parent pool). | | exactAmountsIn | uint256[] memory | Amount of each underlying token in, sorted according to tokensIn array | | minBptAmountOut | uint256 | Expected minimum amount of parent pool tokens to receive | +| wethIsEth | bool | If true, incoming ETH will be wrapped to WETH and outgoing WETH will be unwrapped to ETH | | userData | bytes calldata | Additional (optional) data required for the operation | **Returns:** @@ -137,6 +139,7 @@ function removeLiquidityProportionalNestedPool( uint256 exactBptAmountIn, address[] memory tokensOut, uint256[] memory minAmountsOut, + bool wethIsEth, bytes memory userData ) external returns (uint256[] memory amountsOut); ``` @@ -150,6 +153,7 @@ Adds liquidity unbalanced to a nested pool. A nested pool is one in which one or | exactBptAmountIn | uint256 | Exact amount of `parentPool` tokens provided | | tokensOut | uint256[] memory | Output token addresses, sorted by user preference. `tokensOut` array must have all tokens from child pools and all tokens that are not BPTs from the nested pool (parent pool). If not all tokens are informed, balances are not settled and the operation reverts. Tokens that repeat must be informed only once. | | minAmountsOut | uint256[] memory | Amount of each underlying token in, sorted according to tokensIn array | +| wethIsEth | bool | If true, incoming ETH will be wrapped to WETH and outgoing WETH will be unwrapped to ETH | | userData | bytes calldata | Additional (optional) data required for the operation | **Returns:** @@ -166,6 +170,7 @@ Adds liquidity unbalanced to a nested pool. A nested pool is one in which one or function queryAddLiquidityUnbalancedToERC4626Pool( address pool, uint256[] memory exactUnderlyingAmountsIn, + address sender, bytes memory userData ) external returns (uint256 bptAmountOut); ``` @@ -177,6 +182,7 @@ Query an `addLiquidityUnbalancedToERC4626Pool` operation. |------------|------------------------------------|----------------------------------------------------------------------------------------------| | pool | address | Address of the liquidity pool | | exactUnderlyingAmountsIn | uint256[] memory | Exact amounts of underlying tokens in, sorted in token registration order of wrapped tokens in the pool | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes calldata | Additional (optional) data required for the operation | **Returns:** @@ -191,6 +197,7 @@ Query an `addLiquidityUnbalancedToERC4626Pool` operation. function queryAddLiquidityProportionalToERC4626Pool( address pool, uint256 exactBptAmountOut, + address sender, bytes memory userData ) external returns (uint256[] memory underlyingAmountsIn); ``` @@ -201,6 +208,7 @@ Query an `addLiquidityProportionalToERC4626Pool` operation. |------------|------------------------------------|----------------------------------------------------------------------------------------------| | pool | address | Address of the liquidity pool | | exactBptAmountOut | uint256 | Exact amount of pool tokens to be received | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes calldata | Additional (optional) data required for the operation | **Returns:** @@ -215,6 +223,7 @@ Query an `addLiquidityProportionalToERC4626Pool` operation. function queryRemoveLiquidityProportionalFromERC4626Pool( address pool, uint256 exactBptAmountIn, + address sender, bytes memory userData ) external returns (uint256[] memory underlyingAmountsOut); ``` @@ -225,6 +234,7 @@ Query a `removeLiquidityProportionalFromERC4626Pool` operation. |------------|------------------------------------|----------------------------------------------------------------------------------------------| | pool | address | Address of the liquidity pool | | exactBptAmountIn | uint256 | Exact amount of pool tokens provided | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes calldata | Additional (optional) data required for the operation | **Returns:** @@ -241,6 +251,7 @@ function queryAddLiquidityUnbalancedNestedPool( address pool, address[] memory tokensIn, uint256[] memory exactAmountsIn, + address sender, bytes memory userData ) external returns (uint256 bptAmountOut); ``` @@ -253,6 +264,7 @@ Query an `addLiquidityUnbalancedNestedPool` operation. | pool | address | Address of the liquidity pool | | tokensIn | address[] memory | Input token addresses, sorted by user preference. `tokensIn` array must have all tokens from child pools and all tokens that are not BPTs from the nested pool (parent pool). | | exactAmountsIn | uint256[] memory | Amount of each underlying token in, sorted according to tokensIn array | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes calldata | Additional (optional) data required for the operation | **Returns:** @@ -268,6 +280,7 @@ function queryRemoveLiquidityProportionalNestedPool( address parentPool, uint256 exactBptAmountIn, address[] memory tokensOut, + address sender, bytes memory userData ) external returns (uint256[] memory amountsOut); ``` @@ -280,6 +293,7 @@ Query a `removeLiquidityProportionalNestedPool` operation. | parentPool | address | Address of the highest level pool (which contains BPTs of other pools) | | exactBptAmountIn | uint256 | Exact amount of `parentPool` tokens provided | | tokensOut | address[] memory | Output token addresses, sorted by user preference. `tokensOut` array must have all tokens from child pools and all tokens that are not BPTs from the nested pool (parent pool). If not all tokens are informed, balances are not settled and the operation reverts. Tokens that repeat must be informed only once. | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes calldata | Additional (optional) data required for the operation | **Returns:** diff --git a/docs/developer-reference/contracts/deployment-addresses/sepolia.md b/docs/developer-reference/contracts/deployment-addresses/sepolia.md index e2f6501..56aeb70 100644 --- a/docs/developer-reference/contracts/deployment-addresses/sepolia.md +++ b/docs/developer-reference/contracts/deployment-addresses/sepolia.md @@ -10,10 +10,10 @@ Balancer v3 is in active development. This page shows the latest version of depl | Name | Address | Deployment | |------------------|--------------------------------------------|------------| -| StablePoolFactory| 0x088F634B55C19A3138fd919098fB1320c4aBa6D0 | 9 | -| MockStablePool | 0x47e7cC04016BC65358e8638Ea32a1d35e13ef8CB | 9 | -| WeightedPoolFactory| 0x209e6cE55A89A39329C9666a5B8b371e84572aE8 | 9 | -| MockWeightedPool | 0x78e1c96103f0A76394BE4dC19eB684e0f87D7d5f | 9 | +| StablePoolFactory| 0xcB107E7075add7a95ae7192c052b4e6814bf0ad5 | 11 | +| MockStablePool | 0x5906b98aE7928676019D2B880F9C556bDEC5F4AA | 11 | +| WeightedPoolFactory| 0x9aAD2c188b4eACcA85C44E7A9250dDADcae1A2E9 | 11 | +| MockWeightedPool | 0x88Ab7C08CcD43788738005e3da95598f9dFf4c16 | 11 | ## Core @@ -21,14 +21,15 @@ Balancer v3 is in active development. This page shows the latest version of depl | Name | Address | Deployment | |----------------------|--------------------------------------------|------------| -| ProtocolFeeController| 0x89530f8Abde4d55eD9Ad053949DA9Cac74F8AF14 | 9 | -| VaultAdmin | 0xa91b39DAeF308666a1e8E34BCacE2C3a899AaE78 | 9 | -| VaultExtension | 0xdE8EfE5C22EC8D34a6f6EA1E4AFd49d432a1d5d5 | 9 | -| Vault | 0x30AF3689547354f82C70256894B07C9D0f067BB6 | 9 | -| Router | 0x77eDc69766409C599F06Ef0B551a0990CBfe13A7 | 9 | -| BatchRouter | 0x16Cf31c5c4f92ad6185D583080C84FEeb6074c78 | 9 | -| CompositeLiquidityRouter| 0x89cA59Bc46c00D90C496Fc99f16668b00Dd6B5CC | 9 | -| VaultExplorer | 0x84B15F8dCE31aFA9507b7161e95f20C24aC4C1cd | 9 | +| ProtocolFeeController| 0x0cf640653230a5fA0edb4627660D62eefaBfF8cE | 11 | +| VaultAdmin | 0x2AD9162D9b388b75eB40cBF996AbE8E968670c5C | 11 | +| VaultExtension | 0x59657ebA33Bf0a7dBf03E74a242e6b4F58D6003a | 11 | +| Vault | 0xBC582d2628FcD404254a1e12CB714967Ce428915 | 11 | +| Router | 0x4D2aA7a3CD7F8dA6feF37578A1881cD63Fd3715E | 11 | +| BatchRouter | 0x4232e5EEaA16Bcf483d93BEA469296B4EeF22503 | 11 | +| BufferRouter | 0xD907aFAF02492e054D64da3A14312BdA356fc618 | 11 | +| CompositeLiquidityRouter | 0x2F118d8397D861354751709e1E0c14663e17F5C1 | 11 | +| VaultExplorer | 0xa9F171e84A95c103aD4aFAC3Ec83810f9cA193a8 | 11 | ## Authorization @@ -39,10 +40,10 @@ Balancer v3 is in active development. This page shows the latest version of depl | Name | Address | Deployment | |-------------------------|--------------------------------------------|------------| -| FeeTakingHookExample | 0x0546b036a2A006d3f3730F028528Bf4EaBeb2009 | 9 | -| ExitFeeHookExample | 0x0BA07700fDB18ff14D075e03A863ede2954e3fA2 | 9 | -| DirectionalFeeHookExample| 0x00C1f8dd270480375661B9a2fD100a407e6dCEDa | 9 | -| LotteryHookExample | 0x506C90680336D65ebDC203Cf1283381e72b26e07 | 9 | +| FeeTakingHookExample | 0x790ae803b6c0467C6A4cbDc6d6d712DE34CfdB76 | 11 | +| ExitFeeHookExample | 0x2Aa9D4066DAe16ef001765efF2cA8F41Bde0b019 | 11 | +| DirectionalFeeHookExample| 0xD9e535a65eb38F962B84f7BBD2bf60293bA54058 | 11 | +| LotteryHookExample | 0x0E85194F9eD75F0EFf2b89B73b6AD3053be03853 | 11 | diff --git a/docs/developer-reference/contracts/error-codes.md b/docs/developer-reference/contracts/error-codes.md index d9df2c6..76cfdb5 100644 --- a/docs/developer-reference/contracts/error-codes.md +++ b/docs/developer-reference/contracts/error-codes.md @@ -17,6 +17,7 @@ Balancer uses custom errors which provide a convenient and gas-efficient way to | Error | Comment | | ------- | ----------------------------------------------- | | Disabled| Cannot create a pool after the factory was disabled | +| IndexOutOfBounds| A pool index is beyond the current bounds of the array | ## IERC20MultitokenErrors @@ -75,7 +76,8 @@ Balancer uses custom errors which provide a convenient and gas-efficient way to | SwapFeePercentageTooHigh() | Error raised when the swap fee percentage exceeds the maximum allowed value | | FeePrecisionTooHigh() | Primary fee percentages result in an aggregate fee that cannot be stored with the required precision | | PercentageAboveMax() | A given percentage is above the maximum (usually FixedPoint.ONE,or 1e18 wei) | -| QueriesDisabled() | A user tried to execute a query operation when they were disabled | +| QueriesDisabled() | A user tried to execute a query operation when they were reversibly disabled | +| QueriesDisabledPermanently() | A user tried to execute a query operation when they were permanently disabled | | PoolInRecoveryMode(address) | Cannot enable recovery mode when already enabled | | PoolNotInRecoveryMode(address) | Cannot disable recovery mode when not enabled | | SenderIsNotVault(address) | Error indicating the sender is not the Vault (e.g.,someone is trying to call a permissioned function) | @@ -99,6 +101,7 @@ Balancer uses custom errors which provide a convenient and gas-efficient way to | BufferTotalSupplyTooLow(uint256) | The total supply of a buffer can't be lower than the absolute minimum | | NotEnoughUnderlying(IERC4626,uint256,uint256) | A wrap/unwrap operation consumed more or returned less underlying tokens than it should | | NotEnoughWrapped(IERC4626,uint256,uint256) | A wrap/unwrap operation consumed more or returned less wrapped tokens than it should | +| IssuedSharesBelowMin(uint256,uint256) | Shares issued during initialization are below the requested amount | | DoesNotSupportUnbalancedLiquidity() | Pool does not support adding / removing liquidity with an unbalanced input | | CannotReceiveEth() | The contract should not receive ETH | | NotVaultDelegateCall() | The Vault extension was called by an account directly; it can only be called by the Vault via delegatecall | diff --git a/docs/developer-reference/contracts/protocol-fee-controller-api.md b/docs/developer-reference/contracts/protocol-fee-controller-api.md index 68139ee..1318b30 100644 --- a/docs/developer-reference/contracts/protocol-fee-controller-api.md +++ b/docs/developer-reference/contracts/protocol-fee-controller-api.md @@ -246,6 +246,21 @@ This function withdraws collected protocol fees for a given pool. It sends swap | pool | address | The pool on which fees were collected | | recipient | address | Address to send the tokens | +### `withdrawProtocolFeesForToken` + +```solidity +function withdrawProtocolFeesForToken(address pool, address recipient, IERC20 token) external; +``` +This function withdraws collected protocol fees for a given pool and token. It sends swap and yield protocol fees to the recipient. This is a permissioned call, intended to cover the rare case when one of the tokens cannot be withdrawn (e.g., it is bricked or blocked). + +**Parameters:** + +| Name | Type | Description | +|---|---|---| +| pool | address | The pool on which fees were collected | +| recipient | address | Address to send the tokens | +| token | IERC20 | The token to withdraw + ### `withdrawPoolCreatorFees` ```solidity diff --git a/docs/developer-reference/contracts/router-api.md b/docs/developer-reference/contracts/router-api.md index d2546a2..3303155 100644 --- a/docs/developer-reference/contracts/router-api.md +++ b/docs/developer-reference/contracts/router-api.md @@ -315,7 +315,8 @@ Removes liquidity from a pool with a custom request. ```solidity function removeLiquidityRecovery( address pool, - uint256 exactBptAmountIn + uint256 exactBptAmountIn, + uint256[] memory minAmountsOut ) external returns (uint256[] memory amountsOut); ``` Removes liquidity proportionally, burning an exact pool token amount. Only available in Recovery Mode. @@ -326,6 +327,7 @@ Removes liquidity proportionally, burning an exact pool token amount. Only avail |---|---|---| | pool | address | Address of the liquidity pool | | exactBptAmountIn | uint256 | Exact amount of pool tokens provided | +| minAmountsOut | uint256[] | Minimum amounts of tokens to be received, sorted in token registration order | **Returns:** @@ -405,59 +407,6 @@ Executes a swap operation specifying an exact output token amount. |-------------|-----------|-----------------------------------------------------| | amountIn | uint256 | Calculated amount of input tokens to be sent in exchange for the requested output tokens | - -## ERC4626 Buffers - -### `initializeBuffer` - -```solidity -function initializeBuffer( - IERC4626 wrappedToken, - uint256 amountUnderlyingRaw, - uint256 amountWrappedRaw -) external returns (uint256 issuedShares); -``` -Adds liquidity for the first time to one of the Vault's internal ERC4626 buffers. Buffer operations will revert until the buffer is initialized. - -**Parameters:** - -| Name | Type | Description | -|---|---|---| -| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | -| amountUnderlyingRaw | uint256 | Amount of underlying tokens that will be deposited into the buffer | -| amountWrappedRaw | uint256 | Amount of wrapped tokens that will be deposited into the buffer | - -**Returns:** - -| Name | Type | Description | -|---|---|---| -| issuedShares | uint256 | The amount of tokens sharesOwner has in the buffer, denominated in underlying tokens (This is the BPT of an internal ERC4626 token buffer) | - - -### `addLiquidityToBuffer` - -```solidity -function addLiquidityToBuffer( - IERC4626 wrappedToken, - uint256 exactSharesToIssue, -) external returns (uint256 amountUnderlyingRaw, uint256 amountWrappedRaw); -``` -Adds liquidity proportionally to a yield-bearing buffer (one of the Vault's internal ERC4626 token buffers). This limitation is necessary to avoid having multiple "wrap/unwrap" paths. - -**Parameters:** - -| Name | Type | Description | -|---|---|---| -| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | -| exactSharesToIssue | uint256 | The value in underlying tokens that `sharesOwner` wants to add to the buffer, in underlying token decimals | - -**Returns:** - -| Name | Type | Description | -|---|---|---| -| amountUnderlyingRaw | uint256 | Amount of underlying tokens deposited into the buffer | -| amountWrappedRaw | uint256 | Amount of wrapped tokens deposited into the buffer | - ## Queries ### `queryAddLiquidityProportional` @@ -466,6 +415,7 @@ Adds liquidity proportionally to a yield-bearing buffer (one of the Vault's inte function queryAddLiquidityProportional( address pool, uint256 exactBptAmountOut, + address sender, bytes memory userData ) external returns (uint256[] memory amountsIn); ``` @@ -477,6 +427,7 @@ Queries an `addLiquidityProportional` operation without actually executing it. |-------------------|-------------|--------------------------------------------------------------------| | pool | address | Address of the liquidity pool | | exactBptAmountOut | uint256 | Exact amount of pool tokens to be received | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -491,6 +442,7 @@ Queries an `addLiquidityProportional` operation without actually executing it. function queryAddLiquidityUnbalanced( address pool, uint256[] memory exactAmountsIn, + address sender, bytes memory userData ) external returns (uint256 bptAmountOut); ``` @@ -502,6 +454,7 @@ Queries an `addLiquidityUnbalanced` operation without actually executing it. |-----------------|-------------|----------------------------------------------------------------| | pool | address | Address of the liquidity pool | | exactAmountsIn | uint256[] | Exact amounts of tokens to be added, sorted in token registration order | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -517,6 +470,7 @@ function queryAddLiquiditySingleTokenExactOut( address pool, IERC20 tokenIn, uint256 exactBptAmountOut, + address sender, bytes memory userData ) external returns (uint256 amountIn); ``` @@ -529,6 +483,7 @@ Queries an `addLiquiditySingleTokenExactOut` operation without actually executin | pool | address | Address of the liquidity pool | | tokenIn | IERC20 | Token used to add liquidity | | exactBptAmountOut | uint256 | Expected exact amount of pool tokens to receive | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -544,6 +499,7 @@ function queryAddLiquidityCustom( address pool, uint256[] memory maxAmountsIn, uint256 minBptAmountOut, + address sender, bytes memory userData ) external returns (uint256[] memory amountsIn, uint256 bptAmountOut, bytes memory returnData); ``` @@ -556,6 +512,7 @@ Queries an `addLiquidityCustom` operation without actually executing it. | pool | address | Address of the liquidity pool | | maxAmountsIn | uint256[] | Maximum amounts of tokens to be added, sorted in token registration order | | minBptAmountOut | uint256 | Expected minimum amount of pool tokens to receive | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -572,6 +529,7 @@ Queries an `addLiquidityCustom` operation without actually executing it. function queryRemoveLiquidityProportional( address pool, uint256 exactBptAmountIn, + address sender, bytes memory userData ) external returns (uint256[] memory amountsOut); ``` @@ -583,6 +541,7 @@ Queries a `removeLiquidityProportional` operation without actually executing it. |-------------------|-------------|--------------------------------------------------------| | pool | address | Address of the liquidity pool | | exactBptAmountIn | uint256 | Exact amount of pool tokens provided for the query | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -598,6 +557,7 @@ function queryRemoveLiquiditySingleTokenExactIn( address pool, uint256 exactBptAmountIn, IERC20 tokenOut, + address sender, bytes memory userData ) external returns (uint256 amountOut); ``` @@ -610,6 +570,7 @@ Queries a `removeLiquiditySingleTokenExactIn` operation without actually executi | pool | address | Address of the liquidity pool | | exactBptAmountIn | uint256 | Exact amount of pool tokens provided for the query | | tokenOut | IERC20 | Token used to remove liquidity | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -625,6 +586,7 @@ function queryRemoveLiquiditySingleTokenExactOut( address pool, IERC20 tokenOut, uint256 exactAmountOut, + address sender, bytes memory userData ) external returns (uint256 bptAmountIn); ``` @@ -637,6 +599,7 @@ Queries `a removeLiquiditySingleTokenExactOut` operation without actually execut | pool | address | Address of the liquidity pool | | tokenOut | IERC20 | Token used to remove liquidity | | exactAmountOut | uint256 | Exact amount of tokens to receive | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -652,6 +615,7 @@ function queryRemoveLiquidityCustom( address pool, uint256 maxBptAmountIn, uint256[] memory minAmountsOut, + address sender, bytes memory userData ) external returns (uint256 bptAmountIn, uint256[] memory amountsOut, bytes memory returnData); ``` @@ -664,6 +628,7 @@ Queries a `removeLiquidityCustom` operation without actually executing it. | pool | address | Address of the liquidity pool | | maxBptAmountIn | maxBptAmountIn | Maximum amount of pool tokens provided | | minAmountsOut | uint256[] | Expected minimum amounts of tokens to receive, sorted in token registration order | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -705,6 +670,7 @@ function querySwapSingleTokenExactIn( IERC20 tokenIn, IERC20 tokenOut, uint256 exactAmountIn, + address sender, bytes calldata userData ) external returns (uint256 amountCalculated); ``` @@ -718,6 +684,7 @@ Queries an `swapSingleTokenExactIn` operation without actually executing it. | tokenIn | IERC20 | Token to be swapped from | | tokenOut | IERC20 | Token to be swapped to | | exactAmountIn | uint256 | Exact amount of input tokens to send | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -734,6 +701,7 @@ function querySwapSingleTokenExactOut( IERC20 tokenIn, IERC20 tokenOut, uint256 exactAmountOut, + address sender, bytes calldata userData ) external returns (uint256 amountCalculated); ``` @@ -747,6 +715,7 @@ Queries an `swapSingleTokenExactOut` operation without actually executing it. | tokenIn | IERC20 | Token to be swapped from | | tokenOut | IERC20 | Token to be swapped to | | exactAmountIn | uint256 | Exact amount of input tokens to receive | +| sender | address | The sender passed to the operation. It can influence results (e.g., with user-dependent hooks) | | userData | bytes | Additional (optional) data required for the query | **Returns:** @@ -757,7 +726,7 @@ Queries an `swapSingleTokenExactOut` operation without actually executing it. ## Router common -These functions are shared between the `Router`, `BatchRouter`, and `CompositeLiquidityRouter` (defined in `RouterCommon`). +These functions are shared between the `Router`, `BatchRouter`, `BufferRouter`, and `CompositeLiquidityRouter` (defined in `RouterCommon`). ### `permitBatchAndCall` diff --git a/docs/developer-reference/contracts/vault-api.md b/docs/developer-reference/contracts/vault-api.md index 7c52d66..8bfda60 100644 --- a/docs/developer-reference/contracts/vault-api.md +++ b/docs/developer-reference/contracts/vault-api.md @@ -144,6 +144,25 @@ This `VaultExtension` function retrieves the reserve (i.e., total Vault balance) |---|---|---| | | uint256 | The amount of reserves for the given token | +### `getAddLiquidityCalledFlag` + +```solidity +function getAddLiquidityCalledFlag(address pool) external view returns (bool); +``` +This `VaultExtension` function retrieves the value of the falg used to detect and tax "round trip" transactions (adding and removing liquidity in the same pool). + +**Parameters:** + +| Name | Type | Description | +|---|---|---| +| pool | address | The pool on which to check the flag | + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| | bool | True if addLiquidity has been called on this pool in the current transaction | + ## Swaps ### `swap` @@ -468,6 +487,7 @@ function initializeBuffer( IERC4626 wrappedToken, uint256 amountUnderlyingRaw, uint256 amountWrappedRaw, + uint256 minIssuedShares, address sharesOwner ) external returns (uint256 issuedShares); ``` @@ -480,6 +500,7 @@ This `VaultAdmin` function adds liquidity to an internal ERC4626 buffer in the V | wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | | amountUnderlyingRaw | uint256 | Amount of underlying tokens that will be deposited into the buffer | | amountWrappedRaw | uint256 | Amount of wrapped tokens that will be deposited into the buffer | +| minIssuedShares | uint256 | Minimum amount of shares to receive from the buffer, expressed in underlying token native decimals | | sharesOwner | address | Address of the contract that will own the liquidity. Only this contract will be able to remove liquidity from the buffer | ### `addLiquidityToBuffer` @@ -487,6 +508,8 @@ This `VaultAdmin` function adds liquidity to an internal ERC4626 buffer in the V ```solidity function addLiquidityToBuffer( IERC4626 wrappedToken, + uint256 maxAmountUnderlyingInRaw, + uint256 maxAmountWrappedInRaw, uint256 exactSharesToIssue, address sharesOwner ) external returns (uint256 amountUnderlyingRaw, uint256 amountWrappedRaw); @@ -498,8 +521,9 @@ This `VaultAdmin` function adds liquidity proportionally to an internal ERC4626 | Name | Type | Description | |---|---|---| | wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | -| amountUnderlyingRaw | uint256 | Amount of underlying tokens that will be deposited into the buffer | -| amountWrappedRaw | uint256 | Amount of wrapped tokens that will be deposited into the buffer | +| maxAmountUnderlyingInRaw | uint256 | Amount of underlying tokens that will be deposited into the buffer | +| maxAmountWrappedInRaw | uint256 | Amount of wrapped tokens that will be deposited into the buffer | +| exactSharesToIssue | uint256 | The value in underlying tokens that `sharesOwner` wants to add to the buffer in underlying token decimals | | sharesOwner | address | Address of the contract that will own the liquidity. Only this contract will be able to remove liquidity from the buffer | ### `removeLiquidityFromBuffer` @@ -507,7 +531,9 @@ This `VaultAdmin` function adds liquidity proportionally to an internal ERC4626 ```solidity function removeLiquidityFromBuffer( IERC4626 wrappedToken, - uint256 sharesToRemove + uint256 sharesToRemove, + uint256 minAmountUnderlyingOutRaw, + uint256 minAmountWrappedOutRaw ) external returns (uint256 removedUnderlyingBalanceRaw, uint256 removedWrappedBalanceRaw); ``` This `VaultAdmin` function removes liquidity from an internal ERC4626 buffer in the Vault. Only proportional exits are supported. Note that the `sharesOwner` here is the msg.sender; unlike initialize, add, and other buffer operations, the entrypoint for this function is the Vault itself. @@ -518,12 +544,14 @@ This `VaultAdmin` function removes liquidity from an internal ERC4626 buffer in |---|---|---| | wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | | sharesToRemove | uint256 | Amount of shares to remove from the buffer. Cannot be greater than sharesOwner total shares | +| minAmountUnderlyingOutRaw | uint256 | Minimum amount of underlying tokens to receive from the buffer. It is expressed in underlying token native decimals | +| minAmountWrappedOutRaw | uint256 | Minimum amount of wrapped tokens to receive from the buffer. It is expressed in wrapped token native decimals | ### `getBufferOwnerShares` ```solidity function getBufferOwnerShares( - IERC20 wrappedToken, + IERC4626 wrappedToken, address liquidityOwner ) external view returns (uint256 ownerShares); ``` @@ -536,10 +564,37 @@ This `VaultAdmin` function returns the shares (internal buffer BPT) of a liquidi | wrappedToken | IERC20 | Address of the wrapped token that implements IERC4626 | | liquidityOwner | address | Address of the user that owns liquidity in the wrapped token's buffer | +**Returns:** + +| Name | Type | Description | +|---|---|---| +| ownerShares | uint256 | Amount of shares allocated to the liquidity owner, in native underlying token decimals | + +### `getBufferAsset` + +```solidity +function getBufferAsset( + IERC4626 wrappedToken +) external view returns (address underlyingToken); +``` +This `VaultAdmin` function returns the shares (internal buffer BPT) of a liquidity owner: a user that deposited assets in the buffer. + +**Parameters:** + +| Name | Type | Description | +|---|---|---| +| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| underlyingToken | address | Address of the underlying token for the buffer | + ### `getBufferTotalShares` ```solidity -function getBufferTotalShares(IERC20 wrappedToken) external view returns (uint256 bufferShares); +function getBufferTotalShares(IERC4626 wrappedToken) external view returns (uint256 bufferShares); ``` This `VaultAdmin` function returns the supply shares (internal buffer BPT) of the ERC4626 buffer. @@ -547,13 +602,13 @@ This `VaultAdmin` function returns the supply shares (internal buffer BPT) of th | Name | Type | Description | |---|---|---| -| wrappedToken | IERC20 | Address of the wrapped token that implements IERC4626 | +| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | ### `getBufferBalance` ```solidity function getBufferBalance( - IERC20 wrappedToken + IERC4626 wrappedToken ) external view returns (uint256 underlyingBalanceRaw, uint256 wrappedBalanceRaw); ``` This `VaultAdmin` function returns the amount of underlying and wrapped tokens deposited in the internal buffer of the vault. @@ -562,7 +617,14 @@ This `VaultAdmin` function returns the amount of underlying and wrapped tokens d | Name | Type | Description | |---|---|---| -| wrappedToken | IERC20 | Address of the wrapped token that implements IERC4626 | +| wrappedToken | IERC4626 | Address of the wrapped token that implements IERC4626 | + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| underlyingBalanceRaw | uint256 | Amount of underlying tokens deposited into the buffer, in native token decimals | +| wrappedBalanceRaw | uint256 | Amount of wrapped tokens deposited into the buffer, in native token decimals | ## Authentication ### `getAuthorizer` @@ -758,7 +820,7 @@ This `VaultExtension` function approves a spender to spend pool tokens on behalf ```solidity function transfer(address owner, address to, uint256 amount) external returns (bool); ``` -This `VaultExtension` function transfers pool token from owner to a recipient. +This `Vault` function transfers pool token from owner to a recipient. **Parameters:** @@ -779,7 +841,7 @@ This `VaultExtension` function transfers pool token from owner to a recipient. ```solidity function transferFrom(address spender, address from, address to, uint256 amount) external returns (bool); ``` -This `VaultExtension` function transfers pool token from a sender to a recipient using an allowance. +This `Vault` function transfers pool token from a sender to a recipient using an allowance. **Parameters:** @@ -1069,7 +1131,8 @@ This `VaultExtension` function checks whether a pool is in recovery mode. function removeLiquidityRecovery( address pool, address from, - uint256 exactBptAmountIn + uint256 exactBptAmountIn, + uint256[] memory minAmountsOut ) external returns (uint256[] memory amountsOut); ``` This `VaultExtension` function removes liquidity from a pool specifying exact pool tokens in, with proportional token amounts out. The request is implemented by the Vault without any interaction with the pool, ensuring that it works the same for all pools, and cannot be disabled by a new pool type. @@ -1081,6 +1144,7 @@ This `VaultExtension` function removes liquidity from a pool specifying exact po | pool | address | Address of the pool | | from | address | Address of user to burn pool tokens from | | exactBptAmountIn | uint256 | Input pool token amount | +| minAmountsOut | uint256[] | Minimum amounts of tokens to be received, sorted in token registration order | **Returns:** @@ -1152,7 +1216,33 @@ This `VaultExtension` function performs a callback on `msg.sender` with argument ```solidity function isQueryDisabled() external view returns (bool); ``` -This `VaultExtension` function checks if the queries are enabled on the Vault. +This `VaultExtension` function checks if the queries reversibly disabled on the Vault. + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| | bool | If true, then queries are disabled | + +### `isQueryDisabledPermanently` + +```solidity +function isQueryDisabledPermanently() external view returns (bool); +``` +This `VaultExtension` function checks if the queries are permanently disabled on the Vault. + +**Returns:** + +| Name | Type | Description | +|---|---|---| +| | bool | If true, then queries are disabled | + +### `emitAuxiliaryEvent` + +```solidity +function emitAuxiliaryEvent(string calldata eventKey, bytes calldata eventData) external; +``` +This `VaultExtension` function checks if the queries are permanently disabled on the Vault. **Returns:** @@ -1165,7 +1255,21 @@ This `VaultExtension` function checks if the queries are enabled on the Vault. ```solidity function disableQuery() external; ``` -This `VaultAdmin` function disables queries functionality on the Vault. It can only be called by governance. +This `VaultAdmin` function reversibly disables query functionality on the Vault. It can only be called by governance. + +### `disableQueryPermanently` + +```solidity +function disableQueryPermanently() external; +``` +This `VaultAdmin` function permanently disables query functionality on the Vault. It can only be called by governance. + +### `enableQuery` + +```solidity +function enableQuery() external; +``` +This `VaultAdmin` function re-enables reversibly disabled query functionality on the Vault. It can only be called by governance. ## Constants ### `getPauseWindowEndTime` diff --git a/docs/integration-guides/aggregators/useful-resources.md b/docs/integration-guides/aggregators/useful-resources.md index bf4d805..593160e 100644 --- a/docs/integration-guides/aggregators/useful-resources.md +++ b/docs/integration-guides/aggregators/useful-resources.md @@ -7,9 +7,11 @@ title: Useful Resources * [Deployment Addresses](/developer-reference/contracts/deployment-addresses/mainnet.html) * [Router ABI](/developer-reference/contracts/abi/router.md) * [BatchRouter ABI](/developer-reference/contracts/abi/batch-router.md) +* [BufferRouter ABI](/developer-reference/contracts/abi/buffer-router.md) * [CompositeLiquidityRouter ABI](/developer-reference/contracts/abi/composite-liquidity-router.md) * [Router API](/developer-reference/contracts/router-api.md) * [BatchRouter API](/developer-reference/contracts/batch-router-api.md) +* [BufferRouter API](/developer-reference/contracts/buffer-router-api.md) * [CompositeLiquidityRouter API](/developer-reference/contracts/composite-liquidity-router-api.md) * [Pool Maths Reference](https://github.com/balancer/balancer-sor/blob/master/src/pools/weightedPool/weightedMath.ts) * [Vault API](/developer-reference/contracts/vault-api.md) From 99a8fec99de6010b931564b7a4591e7bc0fbea33 Mon Sep 17 00:00:00 2001 From: Jeff Bennett Date: Mon, 25 Nov 2024 23:08:52 -0500 Subject: [PATCH 2/3] docs: document best practices for initializing buffers --- docs/developer-reference/contracts/buffer-router-api.md | 2 +- .../contracts/composite-liquidity-router-api.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/developer-reference/contracts/buffer-router-api.md b/docs/developer-reference/contracts/buffer-router-api.md index 42764c7..e2b6022 100644 --- a/docs/developer-reference/contracts/buffer-router-api.md +++ b/docs/developer-reference/contracts/buffer-router-api.md @@ -19,7 +19,7 @@ function initializeBuffer( uint256 minIssuedShares ) external returns (uint256 issuedShares); ``` -Adds liquidity for the first time to one of the Vault's internal ERC4626 buffers. Buffer operations will revert until the buffer is initialized. +Adds liquidity for the first time to one of the Vault's internal ERC4626 buffers. Buffer operations will revert until the buffer is initialized. To avoid unexpected behavior, always initialize buffers before creating or initializing any pools that contain the wrapped tokens to be used with them. **Parameters:** diff --git a/docs/developer-reference/contracts/composite-liquidity-router-api.md b/docs/developer-reference/contracts/composite-liquidity-router-api.md index 52a3f77..4ad5849 100644 --- a/docs/developer-reference/contracts/composite-liquidity-router-api.md +++ b/docs/developer-reference/contracts/composite-liquidity-router-api.md @@ -24,7 +24,7 @@ function addLiquidityUnbalancedToERC4626Pool( bytes memory userData ) external payable returns (uint256 bptAmountOut); ``` -Add arbitrary amounts of underlying tokens to an ERC4626 pool through the buffer. An "ERC4626 pool" contains IERC4626 yield-bearing tokens (e.g., waDAI). +Add arbitrary amounts of underlying tokens to an ERC4626 pool through the buffer. An "ERC4626 pool" contains IERC4626 yield-bearing tokens (e.g., waDAI). Ensure that any buffers associated with the wrapped tokens in the ERC4626 pool have been initialized before initializing or adding liquidity to the "parent" pool, and also make sure limits are set properly. **Parameters:** @@ -53,7 +53,7 @@ function addLiquidityProportionalToERC4626Pool( bytes memory userData ) external payable returns (uint256[] memory underlyingAmountsIn); ``` -Add proportional amounts of underlying tokens to an ERC4626 pool through the buffer. An "ERC4626 pool" contains IERC4626 yield-bearing tokens (e.g., waDAI). +Add proportional amounts of underlying tokens to an ERC4626 pool through the buffer. An "ERC4626 pool" contains IERC4626 yield-bearing tokens (e.g., waDAI). Ensure that any buffers associated with the wrapped tokens in the ERC4626 pool have been initialized before initializing or adding liquidity to the "parent" pool, and also make sure limits are set properly. **Parameters:** From 0a8d6330f38ecf00fef12c60f72c1eb5f4e5d8ff Mon Sep 17 00:00:00 2001 From: mkflow27 Date: Wed, 27 Nov 2024 14:11:16 +0100 Subject: [PATCH 3/3] docs: add buffer router abi --- .../contracts/abi/buffer-router.md | 455 +++++++++++++++++- 1 file changed, 454 insertions(+), 1 deletion(-) diff --git a/docs/developer-reference/contracts/abi/buffer-router.md b/docs/developer-reference/contracts/abi/buffer-router.md index a44f27a..884beab 100644 --- a/docs/developer-reference/contracts/abi/buffer-router.md +++ b/docs/developer-reference/contracts/abi/buffer-router.md @@ -2,8 +2,461 @@ order: 2 title: Buffer Router --- + # Buffer Router ABI ```json - +[ + { + "inputs": [ + { "internalType": "contract IVault", "name": "vault", "type": "address" }, + { "internalType": "contract IWETH", "name": "weth", "type": "address" }, + { + "internalType": "contract IPermit2", + "name": "permit2", + "type": "address" + }, + { "internalType": "string", "name": "version", "type": "string" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { "internalType": "address", "name": "target", "type": "address" } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { "inputs": [], "name": "ErrorSelectorNotFound", "type": "error" }, + { "inputs": [], "name": "EthTransfer", "type": "error" }, + { "inputs": [], "name": "FailedInnerCall", "type": "error" }, + { "inputs": [], "name": "InputLengthMismatch", "type": "error" }, + { "inputs": [], "name": "InsufficientEth", "type": "error" }, + { "inputs": [], "name": "ReentrancyGuardReentrantCall", "type": "error" }, + { + "inputs": [ + { "internalType": "uint8", "name": "bits", "type": "uint8" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" } + ], + "name": "SenderIsNotVault", + "type": "error" + }, + { "inputs": [], "name": "SwapDeadline", "type": "error" }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxAmountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxAmountWrappedIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exactSharesToIssue", + "type": "uint256" + } + ], + "name": "addLiquidityToBuffer", + "outputs": [ + { + "internalType": "uint256", + "name": "amountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountWrappedIn", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxAmountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxAmountWrappedIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exactSharesToIssue", + "type": "uint256" + }, + { "internalType": "address", "name": "sharesOwner", "type": "address" } + ], + "name": "addLiquidityToBufferHook", + "outputs": [ + { + "internalType": "uint256", + "name": "amountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountWrappedIn", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getSender", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exactAmountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exactAmountWrappedIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minIssuedShares", + "type": "uint256" + } + ], + "name": "initializeBuffer", + "outputs": [ + { "internalType": "uint256", "name": "issuedShares", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exactAmountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exactAmountWrappedIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minIssuedShares", + "type": "uint256" + }, + { "internalType": "address", "name": "sharesOwner", "type": "address" } + ], + "name": "initializeBufferHook", + "outputs": [ + { "internalType": "uint256", "name": "issuedShares", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes[]", "name": "data", "type": "bytes[]" } + ], + "name": "multicall", + "outputs": [ + { "internalType": "bytes[]", "name": "results", "type": "bytes[]" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "uint256", "name": "nonce", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "internalType": "struct IRouterCommon.PermitApproval[]", + "name": "permitBatch", + "type": "tuple[]" + }, + { + "internalType": "bytes[]", + "name": "permitSignatures", + "type": "bytes[]" + }, + { + "components": [ + { + "components": [ + { "internalType": "address", "name": "token", "type": "address" }, + { + "internalType": "uint160", + "name": "amount", + "type": "uint160" + }, + { + "internalType": "uint48", + "name": "expiration", + "type": "uint48" + }, + { "internalType": "uint48", "name": "nonce", "type": "uint48" } + ], + "internalType": "struct IAllowanceTransfer.PermitDetails[]", + "name": "details", + "type": "tuple[]" + }, + { "internalType": "address", "name": "spender", "type": "address" }, + { + "internalType": "uint256", + "name": "sigDeadline", + "type": "uint256" + } + ], + "internalType": "struct IAllowanceTransfer.PermitBatch", + "name": "permit2Batch", + "type": "tuple" + }, + { "internalType": "bytes", "name": "permit2Signature", "type": "bytes" }, + { "internalType": "bytes[]", "name": "multicallData", "type": "bytes[]" } + ], + "name": "permitBatchAndCall", + "outputs": [ + { "internalType": "bytes[]", "name": "results", "type": "bytes[]" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exactSharesToIssue", + "type": "uint256" + } + ], + "name": "queryAddLiquidityToBuffer", + "outputs": [ + { + "internalType": "uint256", + "name": "amountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountWrappedIn", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exactSharesToIssue", + "type": "uint256" + } + ], + "name": "queryAddLiquidityToBufferHook", + "outputs": [ + { + "internalType": "uint256", + "name": "amountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountWrappedIn", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exactAmountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exactAmountWrappedIn", + "type": "uint256" + } + ], + "name": "queryInitializeBuffer", + "outputs": [ + { "internalType": "uint256", "name": "issuedShares", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exactAmountUnderlyingIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exactAmountWrappedIn", + "type": "uint256" + } + ], + "name": "queryInitializeBufferHook", + "outputs": [ + { "internalType": "uint256", "name": "issuedShares", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exactSharesToRemove", + "type": "uint256" + } + ], + "name": "queryRemoveLiquidityFromBuffer", + "outputs": [ + { + "internalType": "uint256", + "name": "removedUnderlyingBalanceOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "removedWrappedBalanceOut", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC4626", + "name": "wrappedToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exactSharesToRemove", + "type": "uint256" + } + ], + "name": "queryRemoveLiquidityFromBufferHook", + "outputs": [ + { + "internalType": "uint256", + "name": "removedUnderlyingBalanceOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "removedWrappedBalanceOut", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] ```