A starter kit for building on top of Balancer v3. Accelerate the process of creating custom pools and hooks contracts. Concentrate on mastering the core concepts within a swift and responsive environment augmented by a local fork and a frontend pool operations playground.
- Learn the core concepts for building on top of Balancer v3
- Configure and deploy factories, pools, and hooks contracts to a local anvil fork of Sepolia
- Interact with pools via a frontend that runs at localhost:3000
- π§βπ» Environment Setup
- π©βπ« Learn Core Concepts
- π΅οΈ Explore the Examples
- π Create a Custom Pool
- π Create a Pool Factory
- πͺ Create a Pool Hook
- π’ Deploy the Contracts
- π§ͺ Test the Contracts
- Node (>= v18.17)
- Yarn (v1 or v2+)
- Git
- Foundry (>= v0.2.0)
- Ensure you have the latest version of foundry installed
foundryup
- Clone this repo & install dependencies
git clone https://github.com/balancer/scaffold-balancer-v3.git
cd scaffold-balancer-v3
yarn install- Set a
SEPOLIA_RPC_URLin thepackages/foundry/.envfile
SEPOLIA_RPC_URL=...
- Start a local anvil fork of the Sepolia testnet
yarn fork- Deploy the mock tokens, pool factories, pool hooks, and custom pools contracts
By default, the anvil account #0 will be the deployer and recieve the mock tokens and BPT from pool initialization
yarn deploy- Start the nextjs frontend
yarn start- Explore the frontend
- Navigate to http://localhost:3000 to see the home page
- Visit the Pools Page to search by address or select using the pool buttons
- Vist the Debug Page to see the mock tokens, factory, and hooks contracts
- Run the Foundry tests
yarn test
SE-2 offers a variety of configuration options for connecting an account, choosing networks, and deploying contracts
π₯ Burner Wallet
If you do not have an active wallet extension connected to your web browser, then scaffold eth will automatically connect to a "burner wallet" that is randomly generated on the frontend and saved to the browser's local storage. When using the burner wallet, transactions will be instantly signed, which is convenient for quick iterative development.
To force the use of burner wallet, disable your browsers wallet extensions and refresh the page. Note that the burner wallet comes with 0 ETH to pay for gas so you will need to click the faucet button in top right corner. Also the mock tokens for the pool are minted to your deployer account set in .env so you will want to navigate to the "Debug Contracts" page to mint your burner wallet some mock tokens to use with the pool.
π Browser Extension Wallet
- To use your preferred browser extension wallet, ensure that the account you are using matches the PK you previously provided in the
foundry/.envfile - You may need to add a local development network with rpc url
http://127.0.0.1:8545/and chain id31337. Also, you may need to reset the nonce data for your wallet exension if it gets out of sync.
π Debug Contracts Page
The Debug Contracts Page can be useful for viewing and interacting with all of the externally avaiable read and write functions of a contract. The page will automatically hot reload with contracts that are deployed via the 01_DeployConstantSumFactory.s.sol script. We use this handy setup to mint mockERC20 tokens to any connected wallet
π Changing The Frontend Network Connection
- The network the frontend points at is set via
targetNetworksin thescaffold.config.tsfile usingchainsfrom viem. - By default, the frontend runs on a local node at
http://127.0.0.1:8545
const scaffoldConfig = {
targetNetworks: [chains.foundry],π΄ Changing The Forked Network
- By default, the
yarn forkcommand points at sepolia, but any of the network aliases from the[rpc_endpoints]offoundry.tomlcan be used to modify the"fork"alias in thepackages/foundry/package.jsonfile
"fork": "anvil --fork-url ${0:-sepolia} --chain-id 31337 --config-out localhost.json",- To point the frontend at a different forked network, change the
targetForkinscaffold.config.ts
const scaffoldConfig = {
// The networks the frontend can connect to
targetNetworks: [chains.foundry],
// If using chains.foundry as your targetNetwork, you must specify a network to fork
targetFork: chains.sepolia,- Contract Architecture
- Balancer Pool Tokens
- Balancer Pool Types
- Building Custom AMMs
- Exploring Hooks and Custom Routers
- Hook Development Tips
Each of the following examples have turn key deploy scripts that can be found in the foundry/script/ directory
The swap fee percentage is altered by the hook contract before the pool calculates the amount for the swap
An after swap hook makes a request to an oracle contract for a random number
An after remove liquidity hook adjusts the amounts before the vault transfers tokens to the user
- Must inherit from
IBasePoolandBalancerPoolToken - Must implement
onSwap,computeInvariant, andcomputeBalance - Must implement
getMaximumSwapFeePercentageandgetMinimumSwapFeePercentage
- To get started, edit the
ConstantSumPool.solcontract directly or make a copy
After designing a pool contract, the next step is to prepare a factory contract because Balancer's 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
- A pool factory contract must inherit from BasePoolFactory
- Use the internal
_createfunction to deploy a new pool - Use the internal
_registerPoolWithVaultfuction to register a pool immediately after creation
- To get started, edit the
ConstantSumFactory.solcontract directly or make a copy
- A hooks contract must inherit from BasePoolHooks.sol
- A hooks contract should also inherit from VaultGuard.sol
- Must implement
onRegisterto determine if a pool is allowed to use the hook contract - Must implement
getHookFlagsto define which hooks are supported - The
onlyVaultmodifier should be applied to all hooks functions (i.e.onRegister,onBeforeSwap,onAfterSwapect.)
- To get started, edit the
VeBALFeeDiscountHook.solcontract directly or make a copy
The deploy scripts are located in the foundry/script/ directory. To better understand the lifecycle of deploying a pool that uses a hooks contract, see the diagram below
For all the scaffold integrations to work properly, each deploy script must be imported into Deploy.s.sol and inherited by the DeployScript contract in Deploy.s.sol
- Run the following command
yarn deploy- Add a
DEPLOYER_PRIVATE_KEYto thepackages/foundry/.envfile
DEPLOYER_PRIVATE_KEY=0x...
SEPOLIA_RPC_URL=...
The
DEPLOYER_PRIVATE_KEYmust start with0xand must hold enough Sepolia ETH to deploy the contracts. This account will receive the BPT from pool initialization
- Run the following command
yarn deploy --network sepolia
The balancer-v3-monorepo provides testing utility contracts like BasePoolTest and BaseVaultTest. Therefore, the best way to begin writing tests for custom factories, pools, and hooks contracts is to leverage the examples established by the source code.
The ConstantSumFactoryTest roughly mirrors the WeightedPool8020FactoryTest
yarn test --match-contract ConstantSumFactoryTest
The ConstantSumPoolTest roughly mirrors the WeightedPoolTest
yarn test --match-contract ConstantSumPoolTest
The VeBALFeeDiscountHookExampleTest mirrors the VeBALFeeDiscountHookExampleTest
yarn test --match-contract VeBALFeeDiscountHookExampleTest









