Adapters
Supported adapters
Balancer V2

Balancer adapter

Since all interaction with Balancer goes through the vault, there is only a single Vault adapter.

Note that the Balancer adapter restricts the set of pools that can be interacted with. Each poolID has one of 3 statuses:

  1. NOT_ALLOWED - the pool cannot be interacted with.
  2. ALLOWED - both swaps and liquidity provision are supported;
  3. SWAPS_ONLY - only swaps are supported;

The current pool status can be retrieved by calling IBalancerV2Adapter.poolStatus(poolId).

State-changing functions

swap

Performs a swap within a single pool through the Vault.

function swap(SingleSwap memory singleSwap, FundManagement memory, uint256 limit, uint256 deadline)
    external
    returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
singleSwapA struct with swap parameters. See Balancer documentation (opens in a new tab) for details.
limitThe minimum amount of tokens to receive from the swap.
deadlineDeadline for the swap to successfully execute.

funds parameter is ignored, because the adapter uses a single default FundManagement struct for all operations (as it does not use Balancer's internal balances, and sender/recipient is always the Credit Account).

Usage:

import {IBalancerV2Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
import {SingleSwap, FundManagement} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IBalancerV2Vault.sol";
import {IAsset} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IAsset.sol";
 
...
 
 
SingleSwap memory singleSwap = SingleSwap({
    poolId: poolId,
    kind: kind,
    assetIn: IAsset(assetIn),
    assetOut: IAsset(assetOut),
    amount: amount,
    userData: ""
});
 
FundManagement memory funds;
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.swap, (singleSwap, funds, limit, deadline))
});
 
creditFacade.multicall(calls);

swapDiff

Swaps the difference between the current balance of the asset and the specified leftoverAmount.

function swapDiff(SingleSwapDiff memory singleSwapDiff, uint256 limitRateRAY, uint256 deadline)
    external
    returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
singleSwapDiffA struct with swap parameters. Same as SingleSwap, but without SwapKind and with amount replaced by leftoverAmount
limitRateRAYThe minimum exchange rate at which assets will be swapped.
deadlineDeadline for the swap to successfully execute.

Usage:

import {IBalancerV2Adapter, SingleSwapDiff} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
import {IAsset} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IAsset.sol";
 
...
 
 
SingleSwapDiff memory singleSwapDiff = SingleSwapDiff({
    poolId: poolId,
    assetIn: IAsset(assetIn),
    assetOut: IAsset(assetOut),
    leftoverAmount: leftoverAmount,
    userData: ""
});
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.swapDiff, (singleSwapDiff, limitRateRAY, deadline))
});
 
creditFacade.multicall(calls);

batchSwap

Executes Balancer's batchSwap with the passed parameters. Only the funds parameters is changed. See Balancer documentation (opens in a new tab) for details.

function batchSwap(
    SwapKind kind,
    BatchSwapStep[] memory swaps,
    IAsset[] memory assets,
    FundManagement memory,
    int256[] memory limits,
    uint256 deadline
) external returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
kindType of a swap (GIVEN_IN or GIVEN_OUT)
swapsArray of per-step swap parameters. See Balancer documentation (opens in a new tab) for details.
assetsArray of assets that participate in the swap.
limitsLimits for tokens spent and received, corresponding to assets. Negative values denote tokens being received by the user, and positive values denote tokens being spent by the user
deadlineDeadline for the swap to successfully execute.

Usage:

import {IAsset} from "../../integrations/balancer/IAsset.sol";
import {
    IBalancerV2Vault,
    SwapKind,
    FundManagement,
    BatchSwapStep
} from "../../integrations/balancer/IBalancerV2Vault.sol";
import {IBalancerV2Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
 
...
 
BatchSwapStep[] memory steps = new BatchSwapStep[](1);
 
steps[0] = BatchSwapStep({
    poolId: poolId,
    assetInIndex: 0,
    assetOutIndex: 1,
    amount: amount,
    userData: ""
});
 
IAsset[] memory assets = new IAsset[](2);
assets[0] = IAsset(tokenIn);
assets[1] = IAsset(tokenOut);
 
FundManagement memory funds;
 
int256[] memory limits = new int256[](2);
 
limits[0] = 0;
limits[1] = limit;
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.batchSwapStep, (kind, steps, assets, funds, limits, deadline))
});
 
creditFacade.multicall(calls);

joinPool

Deposits assets to receive pool BPT in return.

function joinPool(bytes32 poolId, address, address, JoinPoolRequest memory request)
    external
    returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
poolIdID of the pool to deposit into.
requestStruct encoding data to perform a deposit. See Balancer documentation (opens in a new tab) for more details.

sender and recipient are ignored, as they are automatically set to the Credit Account.

Usage:

import {IBalancerV2Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
import {JoinPoolRequest} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IBalancerV2Vault.sol";
import {IAsset} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IAsset.sol";
 
...
 
address[] memory assets = new address[](2);
 
assets[0] = asset0;
assets[1] = asset1;
 
uint256[] memory maxAmountsIn = new uint256[](2);
 
maxAmountsIn[0] = amount0;
maxAmountsIn[1] = amount1;
 
bytes memory userData = abi.encode(1, maxAmountsIn, minBPT);
 
JoinPoolRequest memory request = JoinPoolRequest({
    assets: assets,
    maxAmountsIn: maxAmountsIn,
    userData: userData,
    fromInternalBalance: false
});
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.joinPool, (poolId, address(0), address(0), request))
});
 
creditFacade.multicall(calls);

joinPoolSingleAsset

Deposits a specified amount of a single asset into the pool for BPT.

function joinPoolSingleAsset(bytes32 poolId, IAsset assetIn, uint256 amountIn, uint256 minAmountOut)
    external
    returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
poolIdID of the pool to deposit into.
assetInAsset to deposit into the pool.
amountInAmount of asset to deposit.
minAmountOutMinimal amount of BPT received

Usage:

import {IBalancerV2Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
import {IAsset} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IAsset.sol";
 
...
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.joinPoolSingleAsset, (poolId, IAsset(assetIn), amountIn, minAmountOut))
});
 
creditFacade.multicall(calls);

joinPoolSingleAssetDiff

Deposits the difference between the current asset balance and leftoverAmount into the pool to receive BPT.

function joinPoolSingleAssetDiff(bytes32 poolId, IAsset assetIn, uint256 leftoverAmount, uint256 minRateRAY)
    external
    returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
poolIdID of the pool to deposit into.
assetInAsset to deposit into the pool.
leftoverAmountAmount of asset to keep on the account.
minRateRAYMinimal resulting exchange rate of asset to BPT.

Usage:

import {IBalancerV2Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
import {IAsset} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IAsset.sol";
 
...
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.joinPoolSingleAssetDiff, (poolId, IAsset(assetIn), leftoverAMount, minRateRAY))
});
 
creditFacade.multicall(calls);

exitPool

Burns BPT to withdraw funds from a pool.

function exitPool(bytes32 poolId, address, address payable, ExitPoolRequest memory request)
    external
    returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
poolIdID of the pool to withdraw from.
requestStruct encoding data to perform a withdrawal. See Balancer documentation (opens in a new tab) for more details.

sender and recipient are ignored, as they are automatically set to the Credit Account.

Usage:

import {IBalancerV2Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
import {ExitPoolRequest} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IBalancerV2Vault.sol";
import {IAsset} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IAsset.sol";
 
...
 
address[] memory assets = new address[](2);
 
assets[0] = asset0;
assets[1] = asset1;
 
uint256[] memory minAmountsOut = new uint256[](2);
 
minAmountsOut[0] = minAmount0;
minAmountsOut[1] = minAmount1;
 
bytes memory userData = abi.encode(1, bptIn);
 
ExitPoolRequest memory request = ExitPoolRequest({
    assets: assets,
    minAmountsOut: minAmountsOut,
    userData: userData,
    toInternalBalance: false
});
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.exitPool, (poolId, address(0), address(0), request))
});
 
creditFacade.multicall(calls);

exitPoolSingleAsset

Burns BPT to receive a single asset from the pool.

function exitPoolSingleAsset(bytes32 poolId, IAsset assetOut, uint256 amountIn, uint256 minAmountOut)
    external
    returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
poolIdID of the pool to withdraw from.
assetOutAsset to withdraw from the pool.
amountInAmount of BPT to burn.
minAmountOutMinimal amount of asset received.

Usage:

import {IBalancerV2Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
import {IAsset} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IAsset.sol";
 
...
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.exitPoolSingleAsset, (poolId, IAsset(assetOut), amountIn, minAmountOut))
});
 
creditFacade.multicall(calls);

exitPoolSingleAssetDiff

Burns the difference between the current balance of BPT and leftoverAmount to receive a single asset from the pool.

function exitPoolSingleAssetDiff(bytes32 poolId, IAsset assetOut, uint256 leftoverAmount, uint256 minAmountOut)
    external
    returns (uint256 tokensToEnable, uint256 tokensToDisable);
ParameterDescription
poolIdID of the pool to withdraw from.
assetOutAsset to withdraw from the pool.
leftoverAmountAmount of BPT to keep on the account.
minRateRAYMinimal exchange rate between BPT and withdrawn asset.

Usage:

import {IBalancerV2Adapter} from "@gearbox-protocol/integrations-v3/contracts/interfaces/balancer/IBalancerV2Adapter.sol";
import {IAsset} from "@gearbox-protocol/integrations-v3/contracts/integrations/balancer/IAsset.sol";
 
...
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = MultiCall({
    target: balancerVaultAdapter,
    callData: abi.encodeCall(IBalancerV2Adapter.exitPoolSingleAssetDiff, (poolId, IAsset(assetOut), leftoverAmount, minRateRAY))
});
 
creditFacade.multicall(calls);

Balancer Multicaller library

The BalancerV2 Vault adapter has a corresponding library that simplifies the MultiCall building API.

Usage example:

import {BalancerV2_Multicaller, BalancerV2_Calls} from "@gearbox-protocol/integrations-v3/test/multicall/balancer/BalancerV2_Calls.sol";
...
 
using BalancerV2_Calls for BalancerV2_Multicaller;
...
 
MultiCall[] memory calls = new MultiCall[](1);
calls[0] = BalancerV2_Multicaller(balancerVaultAdapter).joinPoolSingleAsset(poolId, IAsset(assetIn), amountIn, minAmountOut);
 
creditFacade.multicall(calls);
Last updated on November 16, 2023