Nexera-FiAdapters & DeFi ProtocolsBalancer

Balancer v2 Protocol

Overview

Balancer V2 Protocol revolutionizes DeFi with its automated market maker (AMM) model, empowering users to establish liquidity pools accommodating up to eight tokens in any ratio. At its core lies the Vault, a pivotal component that distinguishes itself by separating AMM logic from token management and accounting.

The Nexera-Fi BalancerAdapter interacts with and utilizes Balancers V2's Vault contract.

In the following sections, we'll provide an overview of this contract and its methods that Nexera-Fi BalancerAdapter interacts with.

Interactions with BalancerAdapter

The Nexera-Fi BalancerAdapter directly interacts with Balancer's Vault by calling the methods presented in the diagram below. Each method plays a distinct role within the Adapter, facilitating strategies to seamlessly integrate liquidity provision, liquidity withdrawal, and token swaps within the Balancer V2 ecosystem.


%%{
  init: {
    'theme': 'neutral',
    'themeVariables': {
      'primaryTextColor': '#fff',
      'primaryBorderColor': '#304230',
      'lineColor': '#eff5f6',
      'secondaryColor': '#006100',
      'tertiaryColor': '#00000f',
      'labelColor': '#00000f'
    }
  }
}%%
graph LR;
 
style Nexera_Fi fill:#8453ed
style Balancer_V2 fill:#4284f5;
style POOLS fill:#87eda6;
 
 
subgraph Nexera_Fi
  A[<b> BalancerAdapter </b>]
end
 
subgraph Balancer_V2
  B["<b>VAULT</b>"]
  subgraph POOLS
    C["<b>...</b>"]
    D["<b>Pool Instance</b>"]
    E["<b>...</b>"]
  end
end
 
A --> |<b>getPool</b>: <i>Retrieve the address of Pools</i>| B
A --> |<b>getPoolTokens</b>: <i>Retrieve Pools' registered tokens</i>| B
A --> |<b>joinPool</b>: <i>Add liquidity to Pools</i>| B
A --> |<b>exitPool</b>: <i>Remove liquidity from Pools</i>| B
A --> |<b>swap</b>: <i>Perform a single swap</i>| B
A --> |<b>batchSwap</b>: <i>Perfom a batch swap</i>| B
 
B -.- |<i>Interacts with</i>| POOLS

Vault

The Vault stands at the heart of Balancer V2. It acts as the central hub for interactions with Balancer Pools, facilitating activities for Liquidity Providers joining and exiting pools, Traders executing swaps, and Asset Managers handling token deposits and withdrawals. As the core entity of Balancer, the Vault is responsible for holding and managing all tokens within each Balancer pool. It functions as the primary gateway for most of Balancer operations, including swaps, joins, and exits, making it an integral component of the Balancer protocol.

In the context of the Nexera-Fi BalancerAdapter, these six methods come into play:

  1. getPool
  2. getPoolTokens
  3. joinPool
  4. exitPool
  5. swap
  6. batchSwap

Methods

getPool

Retrieves the address and specialization setting of the Pool identified by its unique poolId.
Note: The address of the Pool corresponds to the address of its LP token (BPT).

enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN }
 
function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);

This method is invoked by the following BalancerAdapter function:

The Vault's getPool method is utilized in this function to assert that the asset provided in out and expectedIn parameters is consistent with the BPT LP token of the target pool during withdrawl and deposit operations respectively.


getPoolTokens

Retrieves a Pool's registered tokens, the total balance for each, and the latest block when any of the tokens' balances changed.

function getPoolTokens(bytes32 poolId) external view returns (
    IERC20[] memory tokens,
    uint256[] memory balances,
    uint256 lastChangeBlock
);

This method is invoked by the following BalancerAdapter functions:

The _deposit and _withdraw functions within the Adapter rely on the getPoolTokens method of the target pool to assert that the tokens associated with the pool align with those provided in the out and expectedIn parameters during deposit and withdrawal operations, respectively.

In the _withdraw function, the consistency between the target pool tokens and the specified expectedIn tokens is checked. In the _deposit function the consistency between the target pool tokens and the provided out tokens is checked.


joinPool

Joins a Pool by transferring tokens (assets) from the sender into the Pool's balance. This action prompts custom Pool behavior, resulting in the issuance of tokenized Pool shares (BPT) to the designated recipient.

struct JoinPoolRequest {
    IAsset[] assets;
    uint256[] maxAmountsIn;
    bytes userData;
    bool fromInternalBalance;
}
 
function joinPool(
    bytes32 poolId,
    address sender,
    address recipient,
    JoinPoolRequest memory request
) external payable;

This method is invoked by the following BalancerAdapter function:

The _deposit function within the Adapter invokes the Vault's joinPool method to facilitate the depositing of assets into the target pool. The assets to be provided to the pool are specified in the out parameter and are cross-validated with the help of _validatePool function.

Prior to the invcation of the Vault's joinPool method, the Adapter employes a two-step mechanism to ensure a seamless transaction. Initially, it checks the existing allowance of the Vault for the specified assets. If the allowance is greater than 0, the Adapter resets the approval to 0. Subsequently, the Adapter sets the approval amount precisely as specified in the "amount" field of the out parameter.

Note: The respective tokenized pool shares (BPT) are allocated to the Adapter as the recipient.


exitPool

Exits a Pool by transferring tokens (assets) from the Pool's balance to recipient.
This action prompts custom Pool behavior, requesting from sender the respective amount of BPT in return.
The withdrawal amount is constrained by the Pool's available cash balance.

struct ExitPoolRequest {
    IAsset[] assets;
    uint256[] minAmountsOut;
    bytes userData;
    bool toInternalBalance;
}
 
function exitPool(
    bytes32 poolId,
    address sender,
    address payable recipient,
    ExitPoolRequest memory request
) external;

This method is invoked by the following BalancerAdapter function:

The _withdraw function within the Adapter invokes the Vault's exitPool method to facilitate the withdrawl of assets from the target pool. The assets to be taken out of the pool are specified in the expectedIn parameter and are cross-validated with the help of _validatePool function.

Note: The withdrawn assets are allocated to the Adapter as the recipient.


swap

Performs a swap against a single specified Pool.

If the swap is GIVEN_IN (the number of tokens to send 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 is known), it returns the amount of tokens sent to the Pool, which must be less than or equal to limit.

enum SwapKind { GIVEN_IN, GIVEN_OUT }
 
struct SingleSwap {
    bytes32 poolId;
    SwapKind kind;
    IAsset assetIn;
    IAsset assetOut;
    uint256 amount;
    bytes userData;
}
 
struct FundManagement {
    address sender;
    bool fromInternalBalance;
    address payable recipient;
    bool toInternalBalance;
}
 
function swap(
    SingleSwap memory singleSwap,
    FundManagement memory funds,
    uint256 limit,
    uint256 deadline
) external payable returns (uint256);

This method is invoked by the following BalancerAdapter function:

This function initiates the execution of the Vault's swap method. It is triggered within the context of the Adapter's _swap function when SwapOperation is configured as SWAP. This execution condition is based on the encoded SwapExtraData struct which also encapsulates the encoded SingleSwapData struct.


batchSwap

Performs a series of swaps against one or multiple specified Pools. 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

In each individual swap, the caller determines either the amount of tokens sent to or received from the Pool, depending on the kind value.

enum SwapKind { GIVEN_IN, GIVEN_OUT }
 
struct BatchSwapStep {
    bytes32 poolId;
    uint256 assetInIndex;
    uint256 assetOutIndex;
    uint256 amount;
    bytes userData;
}
 
struct FundManagement {
    address sender;
    bool fromInternalBalance;
    address payable recipient;
    bool toInternalBalance;
}
 
function batchSwap(
    SwapKind kind,
    BatchSwapStep[] memory swaps,
    IAsset[] memory assets,
    FundManagement memory funds,
    int256[] memory limits,
    uint256 deadline
) external payable returns (int256[] memory);

This method is invoked by the following BalancerAdapter function:

This function initiates the execution of the Vault's batchSwap method. It is triggered within the context of the Adapter's _swap function when SwapOperation is configured as BATCH_SWAP. This execution condition is based on the encoded SwapExtraData struct.


Please note: For detailed information about Balancer Protocol, consult the official documentation.

On this page