Deploy a Custom AMM Using a Factory

This section is for developers looking to deploy a custom pool contract that has already been written. If you are looking to design a custom AMM with a novel invariant, start here.

Balancer recommends that custom pools be deployed via a factory contract because our off-chain infrastructure uses the factory address as a means to identify the type of pool, which is important for integration into the UI, SDK, and external aggregators.

To fully set up a new custom pool so that normal liquidity operations and swaps are enabled, five required steps must be taken:

  1. Deploy a factory contract that inherits from BasePoolFactory.solopen in new window
  2. Deploy the pool contract using the factory's _create function
  3. Register the pool using the factory's _registerPoolWithVault function
  4. Use Permit2open in new window to approve the Router to spend the tokens that will be used to initialize the pool
  5. Call router.initialize()open in new window to seed the pool with initial liquidity

Tips

To see example foundry scripts for deploying a custom pool using a factory, check out Scaffold Balancer v3open in new window

Creating a Custom Pool Factory Contract

A factory contract should inherit the BasePoolFactory.solopen in new window abstract contract, which sets the table for deploying pools with CREATE3 and streamlines the registration process.

Below, we present an example custom pool factory that uses the ConstantSumPool contract from Build your custom AMM

Factory Constructor Parameters

  • IVault vault: The address of the Balancer vault
  • uint32 pauseWindowDuration: The period, starting from deployment of a factory, during which pools can be paused and unpaused, see FactoryWidePauseWindow.solopen in new window
  • bytes memory creationCode: The creation bytecode of the pool contract used by CREATE3 for deployment

Pool Deployment Parameters

  • bytes memory constructorArgs: The abi encoded constructor args for the custom pool
  • bytes32 salt: Used to compute a unique, deterministic address for each pool deployment

Pool Registration Parameters

Info

Although deploying pools via a factory contract is the recommended approach, it is not mandatory since it is possible to call vault.registerPoolopen in new window directly.

Initializing a Custom Pool

After a custom pool has been deployed and registered, the next step is to add initial liquidity to the pool, which is a three step process:

  1. Ensure the Permit2open in new window contract has been granted sufficient allowance to spend tokens on behalf of the msg.sender
  2. Transfer sufficient allowance to the Routeropen in new window with Permit2.approveopen in new window
  3. Call router.initialize()open in new window

After a pool has been initialized, normal liquidity operations and swaps are instantly enabled.