Skip to content

A full stack prototyping tool for designing and deploying contracts on top of Composable CoW

License

Notifications You must be signed in to change notification settings

bleu/scaffold-composable-cow

Β 
Β 

Repository files navigation

πŸ—οΈ Scaffold Balancer v3

A full stack prototyping tool for building on top of Balancer v3. Accelerate the process of designing and deploying 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.

πŸ› οΈ Tech Stack

Balancer SDK Scaffold ETH 2 Balancer v3 Monorepo

πŸ“š Prerequisites

πŸͺ§ Table Of Contents

  1. Environment Setup πŸ§‘β€πŸ’»
  2. Create a Custom Pool 🌊
  3. Create a Pool Factory 🏭
  4. Create a Pool Hook πŸͺ
  5. Deploy the Contracts 🚒
  6. Test the Contracts πŸ§ͺ

0. Environment Setup πŸ§‘β€πŸ’»

image

πŸ“œ Requirements

πŸƒ Quickstart

  1. Clone this repo & install dependencies
git clone https://github.com/balancer/scaffold-balancer-v3.git
cd scaffold-balancer-v3
yarn install
  1. Set the necessary environment variables in a packages/foundry/.env file 1
DEPLOYER_PRIVATE_KEY=0x...
SEPOLIA_RPC_URL=...
  1. Start a local anvil fork of the Sepolia testnet
yarn fork
  1. Deploy the mock tokens, pool factories, pool hooks, and custom pools contracts 2
yarn deploy
  1. Start the nextjs frontend
yarn start
  1. Explore the frontend
  1. Run the Foundry tests
yarn test

πŸ—οΈ Scaffold ETH 2 Tips

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.

Burner Wallet

Debug Tab Mint

πŸ‘› 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/.env file
  • You may need to add a local development network with rpc url http://127.0.0.1:8545/ and chain id 31337. 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 targetNetworks in the scaffold.config.ts file using chains from 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 fork command points at sepolia, but any of the network aliases from the [rpc_endpoints] of foundry.toml can be used to modify the "fork" alias in the packages/foundry/package.json file
	"fork": "anvil --fork-url ${0:-sepolia} --chain-id 31337 --config-out localhost.json",
  • To point the frontend at a different forked network, change the targetFork in scaffold.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,

1. Create a Custom Pool 🌊

Your journey begins with planning the custom computation logic for the pool, which defines how an AMM exchanges one asset for another.

πŸ“– Review the Docs

πŸ”‘ Recall the Key Requirements

  • Must inherit from IBasePool and BalancerPoolToken
  • Must implement onSwap, computeInvariant, and computeBalance
  • Must implement getMaximumSwapFeePercentage and getMinimumSwapFeePercentage

πŸ“ Write a Custom Pool Contract

  • To get started, edit theConstantSumPool.sol contract directly or make a copy

2. Create a Pool Factory 🏭

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

πŸ“– Review the Docs

πŸ”‘ Recall the Key Requirements

  • A pool factory contract must inherit from BasePoolFactory
  • Use the internal _create function to deploy a new pool
  • Use the internal _registerPoolWithVault fuction to register a pool immediately after creation

πŸ“ Write a Factory Contract

  • To get started, edit theConstantSumFactory.sol contract directly or make a copy

3. Create a Pool Hook πŸͺ

Next, consider further extending the functionality of the custom pool contract with a hooks contract. If your custom pool does not need a hooks contract, use the zero address during pool registration

πŸ“– Review the Docs

πŸ”‘ Recall the Key Requirements

  • A hooks contract must inherit from BasePoolHooks.sol
  • Must implement getHookFlags to define which hooks are supported
  • Must implement onRegister to determine if a pool is allowed to use the hook contract

πŸ“ Write a Hook Contract

  • To get started, edit the VeBALFeeDiscountHook.sol contract directly or make a copy

4. Deploy the Contracts 🚒

The deploy scripts are all located in the foundry/script/ directory and are prefixed with a number based on the order the order they're intended to be run. The mock tokens, factories, and hooks contracts must be deployed before the pools. On the frontend, the Pools page will automatically add a button above the search bar for any pools deployed using the latest factory contract

πŸ› οΈ Adjust the Deploy Scripts

00_DeploySetup.s.sol

Deploys mock tokens, factory contracts, and hooks contracts to be used by pools

  • Set the pauseWindowDuration for the factory contracts
  • Set the mock token names, symbols, and supply
  • Set any hooks contracts constructor args

01_DeployConstantSumPool.s.sol

Deploys, registers, and initializes a Constant Sum Pool

  • Set the pool registration config in the getRegistrationConfig() function
  • Set the pool initialization config in the getInitializationConfig() function

02_DeployConstantProductPool.s.sol

Deploys, registers, and initializes a Constant Product Pool

  • Set the pool registration config in the getRegistrationConfig() function
  • Set the pool initialization config in the getInitializationConfig() function

πŸ“‘ Broadcast the Transactions

To run all the deploy scripts

yarn deploy

To run only the DeploySetup script

yarn deploy:setup

To run only the DeployConstantSumPool script

yarn deploy:sum

To run only the DeployConstantProductPool script

yarn deploy:product

πŸ›ˆ To deploy to the live sepolia testnet, add the --network sepolia flag πŸ›ˆ To modify the yarn commands, edit the "scripts" section of the /foundry/package.json

5. Test the Contracts πŸ§ͺ

Sample tests for the ConstantSumPool and ConstantSumFactory are provided as examples to help you get started writing your own tests.

πŸ‘¨β€πŸ”¬ Testing Factories

The ConstantSumFactoryTest roughly mirrors the WeightedPool8020FactoryTest

yarn test --match-contract ConstantSumFactoryTest

🏊 Testing Pools

The ConstantSumPoolTest roughly mirrors the WeightedPoolTest

yarn test --match-contract ConstantSumPoolTest

🎣 Testing Hooks

  • Coming soonℒ️ after update to 6th testnet deployment of v3

Footnotes

  1. The DEPLOYER_PRIVATE_KEY must start with 0x and must possess enough Sepolia ETH to deploy the contracts. The SEPOLIA_RPC_URL facilitates running a local fork and sending transactions to sepolia testnet ↩

  2. The DEPLOYER_PRIVATE_KEY wallet receives the mock tokens and resulting BPT from pool initialization ↩

About

A full stack prototyping tool for designing and deploying contracts on top of Composable CoW

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 82.9%
  • Solidity 14.3%
  • JavaScript 2.6%
  • Other 0.2%