Architecture
Core components
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.)
- 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.
This design philosophy ensures that building pools on Balancer is intuitive and efficient, with the vault shouldering the burden of complexity, allowing pool creators to unleash their creativity without worrying about accounting details. The Vault is part of the core protocol, but users can build custom pools and routers.
Simplified transaction flow
The following diagram illustrates the usage of each component during a transaction.
The Router acts as the primary interface for accessing the Balancer protocol, offering a user-friendly way to interact with the Balancer Vault.
The Router unlocks the Vault, which allows it to continue by recording all credits and debts generated by operations like adding liquidity, removing liquidity, and swaps.
The Vault processes the operations instructed by the Router, usually forwarding requests to pools. For example, in the case of a swap, the pool's invariant, which is defined in the pool contract, determines the quantity of tokens being either deposited (
EXACT_OUT
swap) in the Vault or withdrawn (EXACT_IN
swap) from the Vault. Once the required token amounts have been calculated, these amounts are recorded as either credit or debt in the Vault.The Vault returns back the operation results to the Router.
The Router settles debts and credits by sending tokens to the Vault to pay debts, and pulling tokens out of the Vault to clear out credits. The Vault verifies that the Router has correctly settled its accrued debts and credits properly. The transaction will only succeed if every single debit and credit has been accurately settled; otherwise, it will be reverted.
Detailed overview
The Balancer Router is the main interface for interacting with Balancer, providing a user-friendly way to access functions and simplify interactions with the Vault. Any smart contract can serve as a Router, tailored to the specific use case. For instance, hooks and pools can "act" as routers and make calls on the Vault. It's also possible to create custom routers to combine Vault operations in novel ways (e.g., interact with a custom protocol).
The Router calls the Vault's
unlock
method and opens up the vault to record debts and credits based on liquidity or swap operations. This allows operations on the Vault to be combined atomically and still ensure correct accounting.With the Vault unlocked, the Vault calls back into the Router. This is where arbitrary logic can be executed, including any combination of calls to Vault primitives, interacting with external protocols, etc. For example, in the case of a swap action, the Vault calls the Router's specific action hook implementation, such as
swapSingleTokenHook
, and passes the initial function payload from step 1 back to the Router to continue the regular transaction flow.At this stage, any address gains authorization to invoke the Vault's functions that require the Vault to be unlocked identifier by the
onlyWhenUnlocked
modifier. This mechanism guarantees the accurate allocation of debt and credit: the Vault will track how many tokens of each kind are owed to it (debt), and how many tokens can be pulled out of it (credit). The inputs from step 1 are passed to the Vault's core functions, such as swap.Each primitive operation performed on the Vault might trigger function calls on pools to calculate the result of the operation:
onSwap
for swapscalculateInvariant
orcomputeBalance
for liquidity management operations (add / remove), depending on the operation kind. These functions calculate the tokens that need to be deposited into or withdrawn from the Vault. Proportional liquidity management operations are an exception to this rule: the math is solved at the Vault level in this case.
The outcomes of these calculations are categorized as either debts or credits, which must be settled at a later stage. Additionally, in the case of liquidity management operations, the required amount of Balancer Pool Tokens (BPT) is minted or burned.
After debts and credits have been recorded and shared with the Router by the Vault, the execution flow is passed to the Router. This allows the Router to be aware of the amounts owed (both by the sender to the Vault, and vice-versa). It is important to mention that the Router contract has the ability to retrieve the current debts and credits associated with the Vault at any point during the execution by calling a specific function on the Vault.
The Router is responsible for settling the remaining debts and credits, which must be done for the transaction to succeed. If ETH or WETH is to be used in the transaction, the Router wraps or unwraps Ether right before settling WETH debts.
When the router is done with settlement, the Vault verifies that all credits and debts accrued during the operations have been settled as the final step. Once the verification is complete, the Vault is locked again. If all debt has been correctly settled, the transaction will succeed; otherwise, it will be reverted.
On top of the basic workflow, pools can be extended with standalone hooks contracts that can be leveraged at different stages of the pool's lifecycle. These hooks contracts can be called either before or after a pool operation (i.e. step 5), depending on how the pool is configured during deployment. By utilizing hooks, developers can customize and enhance the functionality of pools, enabling the integration of features like oracles or time-weighted average market maker capabilities. See hooks article for more detailed information.