From 46d61a42f55848e42bda1b10a30b567acef11e73 Mon Sep 17 00:00:00 2001
From: Matthew Pereira
Date: Mon, 22 Jul 2024 14:20:47 -0700
Subject: [PATCH 1/7] Update deploy script patterns
---
packages/foundry/package.json | 5 +-
packages/foundry/script/00_DeploySetup.s.sol | 62 -
packages/foundry/script/Deploy.s.sol | 36 +
....s.sol => DeployConstantProductPool.s.sol} | 53 +-
...Pool.s.sol => DeployConstantSumPool.s.sol} | 48 +-
.../foundry/script/DeployMockTokens.s.sol | 35 +
packages/foundry/scripts-js/generateTsAbis.js | 2 +-
.../nextjs/contracts/deployedContracts.ts | 1742 +++++++++--------
8 files changed, 1002 insertions(+), 981 deletions(-)
delete mode 100644 packages/foundry/script/00_DeploySetup.s.sol
create mode 100644 packages/foundry/script/Deploy.s.sol
rename packages/foundry/script/{02_DeployConstantProductPool.s.sol => DeployConstantProductPool.s.sol} (79%)
rename packages/foundry/script/{01_DeployConstantSumPool.s.sol => DeployConstantSumPool.s.sol} (83%)
create mode 100644 packages/foundry/script/DeployMockTokens.s.sol
diff --git a/packages/foundry/package.json b/packages/foundry/package.json
index 5d6478b3..c98d1913 100644
--- a/packages/foundry/package.json
+++ b/packages/foundry/package.json
@@ -5,10 +5,7 @@
"account": "node script/ListAccount.js",
"chain": "anvil --config-out localhost.json",
"compile": "forge compile",
- "deploy": "yarn deploy:setup && yarn deploy:sum && yarn deploy:product",
- "deploy:setup": "forge build --build-info --build-info-path out/build-info/ && forge script script/00_DeploySetup.s.sol --rpc-url ${1:-default_network} --broadcast --legacy && node scripts-js/generateTsAbis.js",
- "deploy:sum": "forge script script/01_DeployConstantSumPool.s.sol --rpc-url ${1:-default_network} --broadcast",
- "deploy:product": "forge script script/02_DeployConstantProductPool.s.sol --rpc-url ${1:-default_network} --broadcast",
+ "deploy": "forge build --build-info --build-info-path out/build-info/ && forge script script/Deploy.s.sol --rpc-url ${1:-default_network} --broadcast --legacy && node scripts-js/generateTsAbis.js",
"flatten": "forge flatten",
"fork": "anvil --fork-url ${0:-sepolia} --chain-id 31337 --config-out localhost.json",
"format": "npx prettier --write --plugin=prettier-plugin-solidity 'contracts/**/*.sol' 'test/**/*.sol' 'script/*.sol' 'utils/*.sol'",
diff --git a/packages/foundry/script/00_DeploySetup.s.sol b/packages/foundry/script/00_DeploySetup.s.sol
deleted file mode 100644
index 44a8b413..00000000
--- a/packages/foundry/script/00_DeploySetup.s.sol
+++ /dev/null
@@ -1,62 +0,0 @@
-//SPDX-License-Identifier: MIT
-pragma solidity ^0.8.24;
-
-import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
-import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
-
-import { PoolHelpers } from "./PoolHelpers.sol";
-import { ScaffoldHelpers, console } from "./ScaffoldHelpers.sol";
-import { ConstantSumFactory } from "../contracts/pools/ConstantSumFactory.sol";
-import { ConstantProductFactory } from "../contracts/pools/ConstantProductFactory.sol";
-import { VeBALFeeDiscountHook } from "../contracts/hooks/VeBALFeeDiscountHook.sol";
-import { MockToken1 } from "../contracts/mocks/MockToken1.sol";
-import { MockToken2 } from "../contracts/mocks/MockToken2.sol";
-import { MockVeBAL } from "../contracts/mocks/MockVeBAL.sol";
-
-/**
- * @title Deploy Setup
- * @notice Deploys mock tokens, factory contracts, and hooks contracts to be used by the pools
- * @dev This script runs as part of `yarn deploy`, but can also be run discretely with `yarn deploy:setup`
- * @dev Set the pauseWindowDuration for the factory contracts below
- */
-contract DeploySetup is PoolHelpers, ScaffoldHelpers {
- function run() external virtual {
- uint256 deployerPrivateKey = getDeployerPrivateKey();
-
- uint32 pauseWindowDuration = 365 days; // The period during which pools can be paused and unpaused ( starting from deployment of the factory )
-
- vm.startBroadcast(deployerPrivateKey);
-
- // Deploy the factory contracts
- ConstantSumFactory sumFactory = new ConstantSumFactory(IVault(vault), pauseWindowDuration);
- ConstantProductFactory productFactory = new ConstantProductFactory(IVault(vault), pauseWindowDuration);
- console.log("Constant Sum Factory deployed at: %s", address(sumFactory));
- console.log("Constant Product Factory deployed at: %s", address(productFactory));
-
- // Deploy mock tokens
- IERC20 token1 = new MockToken1("Mock Token 1", "MT1", 1000e18);
- IERC20 token2 = new MockToken2("Mock Token 2", "MT2", 1000e18);
- IERC20 veBAL = new MockVeBAL("Vote-escrow BAL", "veBAL", 1000e18);
- console.log("MockToken1 deployed at: %s", address(token1));
- console.log("MockToken2 deployed at: %s", address(token2));
- console.log("Mock Vote-escrow BAL deployed at: %s", address(veBAL));
-
- // Deploy a hooks contract for the Constant Product Factory
- VeBALFeeDiscountHook poolHooksContract = new VeBALFeeDiscountHook(
- IVault(vault),
- address(productFactory),
- address(veBAL),
- address(router)
- );
- console.log("VeBALFeeDiscountHook deployed at address: %s", address(poolHooksContract));
-
- vm.stopBroadcast();
-
- /**
- * This function generates the file containing the contracts Abi definitions that are carried from /foundry to /nextjs.
- * These definitions are used to derive the types needed in the custom scaffold-eth hooks, for example.
- * This function should be called last.
- */
- exportDeployments();
- }
-}
diff --git a/packages/foundry/script/Deploy.s.sol b/packages/foundry/script/Deploy.s.sol
new file mode 100644
index 00000000..38d543ba
--- /dev/null
+++ b/packages/foundry/script/Deploy.s.sol
@@ -0,0 +1,36 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.8.24;
+
+// import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
+import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
+
+import { PoolHelpers } from "./PoolHelpers.sol";
+import { ScaffoldHelpers } from "./ScaffoldHelpers.sol";
+import { DeployMockTokens } from "./DeployMockTokens.s.sol";
+import { DeployConstantSumPool } from "./DeployConstantSumPool.s.sol";
+import { DeployConstantProductPool } from "./DeployConstantProductPool.s.sol";
+
+/**
+ * @title Deploy Script
+ * @notice Deploys mock tokens, a constant sum pool, and a constant product pool
+ * @dev Run this script with `yarn deploy`
+ */
+contract DeployScript is DeployMockTokens, DeployConstantSumPool, DeployConstantProductPool {
+ function run() external virtual {
+ // Deploy the mock tokens
+ (IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) = deployMockTokens();
+
+ // Deploy a constant sum factory pool
+ deployConstantSumPool(mockToken1, mockToken2);
+
+ // Deploy a constant product pool
+ deployConstantProductPool(mockToken1, mockToken2, mockVeBAL);
+
+ /**
+ * This function generates the file containing the contracts Abi definitions that are carried from /foundry to /nextjs.
+ * These definitions are used to derive the types needed in the custom scaffold-eth hooks, for example.
+ * This function should be called last.
+ */
+ exportDeployments();
+ }
+}
diff --git a/packages/foundry/script/02_DeployConstantProductPool.s.sol b/packages/foundry/script/DeployConstantProductPool.s.sol
similarity index 79%
rename from packages/foundry/script/02_DeployConstantProductPool.s.sol
rename to packages/foundry/script/DeployConstantProductPool.s.sol
index 6ba3de8f..e3b625a0 100644
--- a/packages/foundry/script/02_DeployConstantProductPool.s.sol
+++ b/packages/foundry/script/DeployConstantProductPool.s.sol
@@ -15,42 +15,39 @@ import { DevOpsTools } from "lib/foundry-devops/src/DevOpsTools.sol";
import { PoolHelpers } from "./PoolHelpers.sol";
import { ScaffoldHelpers, console } from "./ScaffoldHelpers.sol";
+import { VeBALFeeDiscountHook } from "../contracts/hooks/VeBALFeeDiscountHook.sol";
import { ConstantProductFactory } from "../contracts/pools/ConstantProductFactory.sol";
/**
* @title Deploy Constant Product Pool
- * @notice Deploys, registers, and initializes a Constant Product Pool
- * @dev Set the registration & initialization configurations in the internal getter functions
- * @dev This script runs as part of `yarn deploy`, but can also be run discretely with `yarn deploy:product`
+ * @notice Deploys a factory and hooks contract before deploying, registering, and initializing a Constant Product Pool
*/
contract DeployConstantProductPool is PoolHelpers, ScaffoldHelpers {
- function run() external virtual {
+ function deployConstantProductPool(IERC20 token1, IERC20 token2, IERC20 veBAL) internal {
+ // Set the deployment configurations
+ uint32 pauseWindowDuration = 365 days;
+ RegistrationConfig memory regConfig = getPoolRegistrationConfig(token1, token2);
+ InitializationConfig memory initConfig = getPoolInitializationConfig(token1, token2);
+
+ // Start creating the transactions
uint256 deployerPrivateKey = getDeployerPrivateKey();
+ vm.startBroadcast(deployerPrivateKey);
- // Grab the latest deployment addresses for the mock tokens, constant product factory, and hooks contract
- address token1 = DevOpsTools.get_most_recent_deployment(
- "MockToken1", // Must match the mock token contract name
- block.chainid
- );
- address token2 = DevOpsTools.get_most_recent_deployment(
- "MockToken2", // Must match the mock token contract name
- block.chainid
- );
- address factory = DevOpsTools.get_most_recent_deployment(
- "ConstantProductFactory", // Must match the mock token contract name
- block.chainid
- );
- address poolHooksContract = DevOpsTools.get_most_recent_deployment(
- "VeBALFeeDiscountHook", // Must match the hooks contract name
- block.chainid
+ // Deploy a constant sum factory contract
+ ConstantProductFactory factory = new ConstantProductFactory(IVault(vault), pauseWindowDuration);
+ console.log("Constant Product Factory deployed at: %s", address(factory));
+
+ // Deploy a hooks contract that permits pools created by the Constant Product factory
+ VeBALFeeDiscountHook poolHooksContract = new VeBALFeeDiscountHook(
+ IVault(vault),
+ address(factory),
+ address(veBAL),
+ address(router)
);
- // Grab arguments for pool deployment and initialization outside of broadcast to save gas
- RegistrationConfig memory regConfig = getRegistrationConfig(IERC20(token1), IERC20(token2));
- InitializationConfig memory initConfig = getInitializationConfig(IERC20(token1), IERC20(token2));
+ console.log("VeBALFeeDiscountHook deployed at address: %s", address(poolHooksContract));
- vm.startBroadcast(deployerPrivateKey);
// Deploy a pool and register it with the vault
- address pool = ConstantProductFactory(factory).create(
+ address pool = factory.create(
regConfig.name,
regConfig.symbol,
regConfig.salt,
@@ -58,7 +55,7 @@ contract DeployConstantProductPool is PoolHelpers, ScaffoldHelpers {
regConfig.swapFeePercentage,
regConfig.protocolFeeExempt,
regConfig.roleAccounts,
- poolHooksContract,
+ address(poolHooksContract),
regConfig.liquidityManagement
);
console.log("Constant Product Pool deployed at: %s", pool);
@@ -83,7 +80,7 @@ contract DeployConstantProductPool is PoolHelpers, ScaffoldHelpers {
* For STANDARD tokens, the rate provider address must be 0, and paysYieldFees must be false.
* All WITH_RATE tokens need a rate provider, and may or may not be yield-bearing.
*/
- function getRegistrationConfig(
+ function getPoolRegistrationConfig(
IERC20 token1,
IERC20 token2
) internal view returns (RegistrationConfig memory regConfig) {
@@ -137,7 +134,7 @@ contract DeployConstantProductPool is PoolHelpers, ScaffoldHelpers {
* @dev Set the pool initialization configurations here
* @notice This is where the amounts of tokens to seed the pool with initial liquidity are set
*/
- function getInitializationConfig(
+ function getPoolInitializationConfig(
IERC20 token1,
IERC20 token2
) internal pure returns (InitializationConfig memory poolInitConfig) {
diff --git a/packages/foundry/script/01_DeployConstantSumPool.s.sol b/packages/foundry/script/DeployConstantSumPool.s.sol
similarity index 83%
rename from packages/foundry/script/01_DeployConstantSumPool.s.sol
rename to packages/foundry/script/DeployConstantSumPool.s.sol
index 7dfa8604..920b5506 100644
--- a/packages/foundry/script/01_DeployConstantSumPool.s.sol
+++ b/packages/foundry/script/DeployConstantSumPool.s.sol
@@ -10,6 +10,7 @@ import {
import { IRateProvider } from "@balancer-labs/v3-interfaces/contracts/vault/IRateProvider.sol";
import { InputHelpers } from "@balancer-labs/v3-solidity-utils/contracts/helpers/InputHelpers.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
+import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
import { DevOpsTools } from "lib/foundry-devops/src/DevOpsTools.sol";
import { PoolHelpers } from "./PoolHelpers.sol";
@@ -19,33 +20,24 @@ import { ConstantSumFactory } from "../contracts/pools/ConstantSumFactory.sol";
/**
* @title Deploy Constant Sum Pool
* @notice Deploys, registers, and initializes a Constant Sum Pool
- * @dev Set the registration & initialization configurations in the internal getter functions below
- * @dev This script runs as part of `yarn deploy`, but can also be run discretely with `yarn deploy:sum`
*/
contract DeployConstantSumPool is PoolHelpers, ScaffoldHelpers {
- function run() external virtual {
- uint256 deployerPrivateKey = getDeployerPrivateKey();
-
- // Grab the latest deployment addresses for the mock tokens and constant sum factory
- address token1 = DevOpsTools.get_most_recent_deployment(
- "MockToken1", // Must match the mock token contract name
- block.chainid
- );
- address token2 = DevOpsTools.get_most_recent_deployment(
- "MockToken2", // Must match the mock token contract name
- block.chainid
- );
- address factory = DevOpsTools.get_most_recent_deployment(
- "ConstantSumFactory", // Must match the factory contract name
- block.chainid
- );
- // Grab arguments for pool deployment and initialization outside of broadcast to save gas
+ function deployConstantSumPool(IERC20 token1, IERC20 token2) internal {
+ // Set the deployment configurations
+ uint32 pauseWindowDuration = 365 days;
RegistrationConfig memory regConfig = getRegistrationConfig(token1, token2);
InitializationConfig memory initConfig = getInitializationConfig(token1, token2);
+ // Start creating the transactions
+ uint256 deployerPrivateKey = getDeployerPrivateKey();
vm.startBroadcast(deployerPrivateKey);
+
+ // Deploy a constant sum factory contract
+ ConstantSumFactory factory = new ConstantSumFactory(IVault(vault), pauseWindowDuration);
+ console.log("Constant Sum Factory deployed at: %s", address(factory));
+
// Deploy a pool and register it with the vault
- address pool = ConstantSumFactory(factory).create(
+ address pool = factory.create(
regConfig.name,
regConfig.symbol,
regConfig.salt,
@@ -78,8 +70,8 @@ contract DeployConstantSumPool is PoolHelpers, ScaffoldHelpers {
* All WITH_RATE tokens need a rate provider, and may or may not be yield-bearing.
*/
function getRegistrationConfig(
- address token1,
- address token2
+ IERC20 token1,
+ IERC20 token2
) internal view returns (RegistrationConfig memory regConfig) {
string memory name = "Constant Sum Pool"; // name for the pool
string memory symbol = "CSP"; // symbol for the BPT
@@ -90,13 +82,13 @@ contract DeployConstantSumPool is PoolHelpers, ScaffoldHelpers {
TokenConfig[] memory tokenConfig = new TokenConfig[](2); // An array of descriptors for the tokens the pool will manage.
tokenConfig[0] = TokenConfig({ // Make sure to have proper token order (alphanumeric)
- token: IERC20(token1),
+ token: token1,
tokenType: TokenType.STANDARD, // STANDARD or WITH_RATE
rateProvider: IRateProvider(address(0)), // The rate provider for a token (see further documentation above)
paysYieldFees: false // Flag indicating whether yield fees should be charged on this token
});
tokenConfig[1] = TokenConfig({ // Make sure to have proper token order (alphanumeric)
- token: IERC20(token2),
+ token: token2,
tokenType: TokenType.STANDARD, // STANDARD or WITH_RATE
rateProvider: IRateProvider(address(0)), // The rate provider for a token (see further documentation above)
paysYieldFees: false // Flag indicating whether yield fees should be charged on this token
@@ -132,12 +124,12 @@ contract DeployConstantSumPool is PoolHelpers, ScaffoldHelpers {
* @notice this is where the amounts of tokens to be initially added to the pool are set
*/
function getInitializationConfig(
- address token1,
- address token2
+ IERC20 token1,
+ IERC20 token2
) internal pure returns (InitializationConfig memory poolInitConfig) {
IERC20[] memory tokens = new IERC20[](2); // Array of tokens to be used in the pool
- tokens[0] = IERC20(token1);
- tokens[1] = IERC20(token2);
+ tokens[0] = token1;
+ tokens[1] = token2;
uint256[] memory exactAmountsIn = new uint256[](2); // Exact amounts of tokens to be added, sorted in token alphanumeric order
exactAmountsIn[0] = 50e18; // amount of token1 to send during pool initialization
exactAmountsIn[1] = 50e18; // amount of token2 to send during pool initialization
diff --git a/packages/foundry/script/DeployMockTokens.s.sol b/packages/foundry/script/DeployMockTokens.s.sol
new file mode 100644
index 00000000..ba09e64a
--- /dev/null
+++ b/packages/foundry/script/DeployMockTokens.s.sol
@@ -0,0 +1,35 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.8.24;
+
+import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
+import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
+
+import { PoolHelpers } from "./PoolHelpers.sol";
+import { ScaffoldHelpers, console } from "./ScaffoldHelpers.sol";
+import { MockToken1 } from "../contracts/mocks/MockToken1.sol";
+import { MockToken2 } from "../contracts/mocks/MockToken2.sol";
+import { MockVeBAL } from "../contracts/mocks/MockVeBAL.sol";
+
+/**
+ * @title Deploy Mock Tokens
+ * @notice Deploys mock tokens for use with pools and hooks
+ */
+contract DeployMockTokens is PoolHelpers, ScaffoldHelpers {
+ function deployMockTokens() internal returns (IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) {
+ uint256 deployerPrivateKey = getDeployerPrivateKey();
+
+ vm.startBroadcast(deployerPrivateKey);
+
+ // For use with pool contracts
+ mockToken1 = new MockToken1("Mock Token 1", "MT1", 1000e18);
+ mockToken2 = new MockToken2("Mock Token 2", "MT2", 1000e18);
+ console.log("MockToken1 deployed at: %s", address(mockToken1));
+ console.log("MockToken2 deployed at: %s", address(mockToken2));
+
+ // For use with VeBALFeeDiscountHook
+ mockVeBAL = new MockVeBAL("Vote-escrow BAL", "veBAL", 1000e18);
+ console.log("Mock Vote-escrow BAL deployed at: %s", address(mockVeBAL));
+
+ vm.stopBroadcast();
+ }
+}
diff --git a/packages/foundry/scripts-js/generateTsAbis.js b/packages/foundry/scripts-js/generateTsAbis.js
index c05c8873..4553e35a 100644
--- a/packages/foundry/scripts-js/generateTsAbis.js
+++ b/packages/foundry/scripts-js/generateTsAbis.js
@@ -60,7 +60,7 @@ function getInheritedFunctions(mainArtifact) {
}
function main() {
- const current_path_to_broadcast = path.join(__dirname, '..', 'broadcast/00_DeploySetup.s.sol');
+ const current_path_to_broadcast = path.join(__dirname, '..', 'broadcast/Deploy.s.sol');
console.log('current_path_to_broadcast', current_path_to_broadcast);
const current_path_to_deployments = path.join(__dirname, '..', 'deployments');
diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts
index 70232685..7c65c0a5 100644
--- a/packages/nextjs/contracts/deployedContracts.ts
+++ b/packages/nextjs/contracts/deployedContracts.ts
@@ -6,28 +6,11 @@ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";
const deployedContracts = {
31337: {
- ConstantSumFactory: {
- address: "0x8e8cB505973E04200554Bd98741086C7Eca9f42a",
+ MockToken1: {
+ address: "0x539383fDc37eE70495088826ec32F6B28153245C",
abi: [
{
type: "constructor",
- inputs: [
- {
- name: "vault",
- type: "address",
- internalType: "contract IVault",
- },
- {
- name: "pauseWindowDuration",
- type: "uint32",
- internalType: "uint32",
- },
- ],
- stateMutability: "nonpayable",
- },
- {
- type: "function",
- name: "create",
inputs: [
{
name: "name",
@@ -40,365 +23,352 @@ const deployedContracts = {
internalType: "string",
},
{
- name: "salt",
- type: "bytes32",
- internalType: "bytes32",
- },
- {
- name: "tokens",
- type: "tuple[]",
- internalType: "struct TokenConfig[]",
- components: [
- {
- name: "token",
- type: "address",
- internalType: "contract IERC20",
- },
- {
- name: "tokenType",
- type: "uint8",
- internalType: "enum TokenType",
- },
- {
- name: "rateProvider",
- type: "address",
- internalType: "contract IRateProvider",
- },
- {
- name: "paysYieldFees",
- type: "bool",
- internalType: "bool",
- },
- ],
- },
- {
- name: "swapFeePercentage",
+ name: "initialSupply",
type: "uint256",
internalType: "uint256",
},
- {
- name: "protocolFeeExempt",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "roleAccounts",
- type: "tuple",
- internalType: "struct PoolRoleAccounts",
- components: [
- {
- name: "pauseManager",
- type: "address",
- internalType: "address",
- },
- {
- name: "swapFeeManager",
- type: "address",
- internalType: "address",
- },
- {
- name: "poolCreator",
- type: "address",
- internalType: "address",
- },
- ],
- },
- {
- name: "poolHooksContract",
- type: "address",
- internalType: "address",
- },
- {
- name: "liquidityManagement",
- type: "tuple",
- internalType: "struct LiquidityManagement",
- components: [
- {
- name: "disableUnbalancedLiquidity",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableAddLiquidityCustom",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableRemoveLiquidityCustom",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableDonation",
- type: "bool",
- internalType: "bool",
- },
- ],
- },
],
- outputs: [
- {
- name: "pool",
- type: "address",
- internalType: "address",
- },
- ],
- stateMutability: "nonpayable",
- },
- {
- type: "function",
- name: "disable",
- inputs: [],
- outputs: [],
stateMutability: "nonpayable",
},
{
type: "function",
- name: "getActionId",
+ name: "allowance",
inputs: [
{
- name: "selector",
- type: "bytes4",
- internalType: "bytes4",
+ name: "owner",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "spender",
+ type: "address",
+ internalType: "address",
},
],
outputs: [
{
name: "",
- type: "bytes32",
- internalType: "bytes32",
+ type: "uint256",
+ internalType: "uint256",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getAuthorizer",
- inputs: [],
- outputs: [
+ name: "approve",
+ inputs: [
{
- name: "",
+ name: "spender",
type: "address",
- internalType: "contract IAuthorizer",
+ internalType: "address",
},
- ],
- stateMutability: "view",
- },
- {
- type: "function",
- name: "getDefaultLiquidityManagement",
- inputs: [],
- outputs: [
{
- name: "liquidityManagement",
- type: "tuple",
- internalType: "struct LiquidityManagement",
- components: [
- {
- name: "disableUnbalancedLiquidity",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableAddLiquidityCustom",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableRemoveLiquidityCustom",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableDonation",
- type: "bool",
- internalType: "bool",
- },
- ],
+ name: "value",
+ type: "uint256",
+ internalType: "uint256",
},
],
- stateMutability: "pure",
- },
- {
- type: "function",
- name: "getDefaultPoolHooksContract",
- inputs: [],
outputs: [
{
name: "",
- type: "address",
- internalType: "address",
+ type: "bool",
+ internalType: "bool",
},
],
- stateMutability: "pure",
+ stateMutability: "nonpayable",
},
{
type: "function",
- name: "getDeploymentAddress",
+ name: "balanceOf",
inputs: [
{
- name: "salt",
- type: "bytes32",
- internalType: "bytes32",
+ name: "account",
+ type: "address",
+ internalType: "address",
},
],
outputs: [
{
name: "",
- type: "address",
- internalType: "address",
+ type: "uint256",
+ internalType: "uint256",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getNewPoolPauseWindowEndTime",
+ name: "decimals",
inputs: [],
outputs: [
{
name: "",
- type: "uint32",
- internalType: "uint32",
+ type: "uint8",
+ internalType: "uint8",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getOriginalPauseWindowEndTime",
- inputs: [],
- outputs: [
+ name: "mint",
+ inputs: [
{
- name: "",
- type: "uint32",
- internalType: "uint32",
+ name: "amount",
+ type: "uint256",
+ internalType: "uint256",
},
],
- stateMutability: "view",
+ outputs: [],
+ stateMutability: "nonpayable",
},
{
type: "function",
- name: "getPauseWindowDuration",
+ name: "name",
inputs: [],
outputs: [
{
name: "",
- type: "uint32",
- internalType: "uint32",
+ type: "string",
+ internalType: "string",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getVault",
+ name: "symbol",
inputs: [],
outputs: [
{
name: "",
- type: "address",
- internalType: "contract IVault",
+ type: "string",
+ internalType: "string",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "isDisabled",
+ name: "totalSupply",
inputs: [],
outputs: [
{
name: "",
- type: "bool",
- internalType: "bool",
+ type: "uint256",
+ internalType: "uint256",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "isPoolFromFactory",
+ name: "transfer",
inputs: [
{
- name: "pool",
+ name: "to",
type: "address",
internalType: "address",
},
- ],
- outputs: [
+ {
+ name: "value",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ ],
+ outputs: [
{
name: "",
type: "bool",
internalType: "bool",
},
],
- stateMutability: "view",
+ stateMutability: "nonpayable",
+ },
+ {
+ type: "function",
+ name: "transferFrom",
+ inputs: [
+ {
+ name: "from",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "to",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "value",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ ],
+ outputs: [
+ {
+ name: "",
+ type: "bool",
+ internalType: "bool",
+ },
+ ],
+ stateMutability: "nonpayable",
},
{
type: "event",
- name: "FactoryDisabled",
- inputs: [],
+ name: "Approval",
+ inputs: [
+ {
+ name: "owner",
+ type: "address",
+ indexed: true,
+ internalType: "address",
+ },
+ {
+ name: "spender",
+ type: "address",
+ indexed: true,
+ internalType: "address",
+ },
+ {
+ name: "value",
+ type: "uint256",
+ indexed: false,
+ internalType: "uint256",
+ },
+ ],
anonymous: false,
},
{
type: "event",
- name: "PoolCreated",
+ name: "Transfer",
inputs: [
{
- name: "pool",
+ name: "from",
+ type: "address",
+ indexed: true,
+ internalType: "address",
+ },
+ {
+ name: "to",
type: "address",
indexed: true,
internalType: "address",
},
+ {
+ name: "value",
+ type: "uint256",
+ indexed: false,
+ internalType: "uint256",
+ },
],
anonymous: false,
},
{
type: "error",
- name: "Disabled",
- inputs: [],
+ name: "ERC20InsufficientAllowance",
+ inputs: [
+ {
+ name: "spender",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "allowance",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ {
+ name: "needed",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ ],
},
{
type: "error",
- name: "PoolPauseWindowDurationOverflow",
- inputs: [],
+ name: "ERC20InsufficientBalance",
+ inputs: [
+ {
+ name: "sender",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "balance",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ {
+ name: "needed",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ ],
},
{
type: "error",
- name: "SenderNotAllowed",
- inputs: [],
+ name: "ERC20InvalidApprover",
+ inputs: [
+ {
+ name: "approver",
+ type: "address",
+ internalType: "address",
+ },
+ ],
},
{
type: "error",
- name: "StandardPoolWithCreator",
- inputs: [],
+ name: "ERC20InvalidReceiver",
+ inputs: [
+ {
+ name: "receiver",
+ type: "address",
+ internalType: "address",
+ },
+ ],
},
- ],
- inheritedFunctions: {},
- },
- ConstantProductFactory: {
- address: "0xC2D1A7c03C0459a8d0Ee885283CE828DE5fFf617",
- abi: [
{
- type: "constructor",
+ type: "error",
+ name: "ERC20InvalidSender",
inputs: [
{
- name: "vault",
+ name: "sender",
type: "address",
- internalType: "contract IVault",
+ internalType: "address",
},
+ ],
+ },
+ {
+ type: "error",
+ name: "ERC20InvalidSpender",
+ inputs: [
{
- name: "pauseWindowDuration",
- type: "uint32",
- internalType: "uint32",
+ name: "spender",
+ type: "address",
+ internalType: "address",
},
],
- stateMutability: "nonpayable",
},
+ ],
+ inheritedFunctions: {
+ allowance: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ approve: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ balanceOf: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ decimals: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ name: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ symbol: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ totalSupply: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ transfer: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ transferFrom: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ },
+ },
+ MockToken2: {
+ address: "0x69d2485148F2F6e408db39C2516D948Ac1CD69Ab",
+ abi: [
{
- type: "function",
- name: "create",
+ type: "constructor",
inputs: [
{
name: "name",
@@ -411,273 +381,160 @@ const deployedContracts = {
internalType: "string",
},
{
- name: "salt",
- type: "bytes32",
- internalType: "bytes32",
+ name: "initialSupply",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ ],
+ stateMutability: "nonpayable",
+ },
+ {
+ type: "function",
+ name: "allowance",
+ inputs: [
+ {
+ name: "owner",
+ type: "address",
+ internalType: "address",
},
{
- name: "tokens",
- type: "tuple[]",
- internalType: "struct TokenConfig[]",
- components: [
- {
- name: "token",
- type: "address",
- internalType: "contract IERC20",
- },
- {
- name: "tokenType",
- type: "uint8",
- internalType: "enum TokenType",
- },
- {
- name: "rateProvider",
- type: "address",
- internalType: "contract IRateProvider",
- },
- {
- name: "paysYieldFees",
- type: "bool",
- internalType: "bool",
- },
- ],
+ name: "spender",
+ type: "address",
+ internalType: "address",
},
+ ],
+ outputs: [
{
- name: "swapFeePercentage",
+ name: "",
type: "uint256",
internalType: "uint256",
},
+ ],
+ stateMutability: "view",
+ },
+ {
+ type: "function",
+ name: "approve",
+ inputs: [
{
- name: "protocolFeeExempt",
+ name: "spender",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "value",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ ],
+ outputs: [
+ {
+ name: "",
type: "bool",
internalType: "bool",
},
- {
- name: "roleAccounts",
- type: "tuple",
- internalType: "struct PoolRoleAccounts",
- components: [
- {
- name: "pauseManager",
- type: "address",
- internalType: "address",
- },
- {
- name: "swapFeeManager",
- type: "address",
- internalType: "address",
- },
- {
- name: "poolCreator",
- type: "address",
- internalType: "address",
- },
- ],
- },
- {
- name: "poolHooksContract",
- type: "address",
- internalType: "address",
- },
- {
- name: "liquidityManagement",
- type: "tuple",
- internalType: "struct LiquidityManagement",
- components: [
- {
- name: "disableUnbalancedLiquidity",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableAddLiquidityCustom",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableRemoveLiquidityCustom",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableDonation",
- type: "bool",
- internalType: "bool",
- },
- ],
- },
],
- outputs: [
- {
- name: "pool",
- type: "address",
- internalType: "address",
- },
- ],
- stateMutability: "nonpayable",
- },
- {
- type: "function",
- name: "disable",
- inputs: [],
- outputs: [],
stateMutability: "nonpayable",
},
{
type: "function",
- name: "getActionId",
+ name: "balanceOf",
inputs: [
{
- name: "selector",
- type: "bytes4",
- internalType: "bytes4",
+ name: "account",
+ type: "address",
+ internalType: "address",
},
],
outputs: [
{
name: "",
- type: "bytes32",
- internalType: "bytes32",
+ type: "uint256",
+ internalType: "uint256",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getAuthorizer",
+ name: "decimals",
inputs: [],
outputs: [
{
name: "",
- type: "address",
- internalType: "contract IAuthorizer",
+ type: "uint8",
+ internalType: "uint8",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getDefaultLiquidityManagement",
- inputs: [],
- outputs: [
- {
- name: "liquidityManagement",
- type: "tuple",
- internalType: "struct LiquidityManagement",
- components: [
- {
- name: "disableUnbalancedLiquidity",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableAddLiquidityCustom",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableRemoveLiquidityCustom",
- type: "bool",
- internalType: "bool",
- },
- {
- name: "enableDonation",
- type: "bool",
- internalType: "bool",
- },
- ],
- },
- ],
- stateMutability: "pure",
- },
- {
- type: "function",
- name: "getDefaultPoolHooksContract",
- inputs: [],
- outputs: [
- {
- name: "",
- type: "address",
- internalType: "address",
- },
- ],
- stateMutability: "pure",
- },
- {
- type: "function",
- name: "getDeploymentAddress",
+ name: "mint",
inputs: [
{
- name: "salt",
- type: "bytes32",
- internalType: "bytes32",
- },
- ],
- outputs: [
- {
- name: "",
- type: "address",
- internalType: "address",
+ name: "amount",
+ type: "uint256",
+ internalType: "uint256",
},
],
- stateMutability: "view",
+ outputs: [],
+ stateMutability: "nonpayable",
},
{
type: "function",
- name: "getNewPoolPauseWindowEndTime",
+ name: "name",
inputs: [],
outputs: [
{
name: "",
- type: "uint32",
- internalType: "uint32",
+ type: "string",
+ internalType: "string",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getOriginalPauseWindowEndTime",
+ name: "symbol",
inputs: [],
outputs: [
{
name: "",
- type: "uint32",
- internalType: "uint32",
+ type: "string",
+ internalType: "string",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getPauseWindowDuration",
+ name: "totalSupply",
inputs: [],
outputs: [
{
name: "",
- type: "uint32",
- internalType: "uint32",
+ type: "uint256",
+ internalType: "uint256",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "getVault",
- inputs: [],
- outputs: [
+ name: "transfer",
+ inputs: [
{
- name: "",
+ name: "to",
type: "address",
- internalType: "contract IVault",
+ internalType: "address",
+ },
+ {
+ name: "value",
+ type: "uint256",
+ internalType: "uint256",
},
],
- stateMutability: "view",
- },
- {
- type: "function",
- name: "isDisabled",
- inputs: [],
outputs: [
{
name: "",
@@ -685,17 +542,27 @@ const deployedContracts = {
internalType: "bool",
},
],
- stateMutability: "view",
+ stateMutability: "nonpayable",
},
{
type: "function",
- name: "isPoolFromFactory",
+ name: "transferFrom",
inputs: [
{
- name: "pool",
+ name: "from",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "to",
type: "address",
internalType: "address",
},
+ {
+ name: "value",
+ type: "uint256",
+ internalType: "uint256",
+ },
],
outputs: [
{
@@ -704,52 +571,159 @@ const deployedContracts = {
internalType: "bool",
},
],
- stateMutability: "view",
+ stateMutability: "nonpayable",
},
{
type: "event",
- name: "FactoryDisabled",
- inputs: [],
+ name: "Approval",
+ inputs: [
+ {
+ name: "owner",
+ type: "address",
+ indexed: true,
+ internalType: "address",
+ },
+ {
+ name: "spender",
+ type: "address",
+ indexed: true,
+ internalType: "address",
+ },
+ {
+ name: "value",
+ type: "uint256",
+ indexed: false,
+ internalType: "uint256",
+ },
+ ],
anonymous: false,
},
{
type: "event",
- name: "PoolCreated",
+ name: "Transfer",
inputs: [
{
- name: "pool",
+ name: "from",
+ type: "address",
+ indexed: true,
+ internalType: "address",
+ },
+ {
+ name: "to",
type: "address",
indexed: true,
internalType: "address",
},
+ {
+ name: "value",
+ type: "uint256",
+ indexed: false,
+ internalType: "uint256",
+ },
],
anonymous: false,
},
{
type: "error",
- name: "Disabled",
- inputs: [],
- },
- {
- type: "error",
- name: "PoolPauseWindowDurationOverflow",
- inputs: [],
- },
- {
- type: "error",
- name: "SenderNotAllowed",
- inputs: [],
- },
- {
- type: "error",
- name: "StandardPoolWithCreator",
- inputs: [],
+ name: "ERC20InsufficientAllowance",
+ inputs: [
+ {
+ name: "spender",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "allowance",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ {
+ name: "needed",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ ],
+ },
+ {
+ type: "error",
+ name: "ERC20InsufficientBalance",
+ inputs: [
+ {
+ name: "sender",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "balance",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ {
+ name: "needed",
+ type: "uint256",
+ internalType: "uint256",
+ },
+ ],
+ },
+ {
+ type: "error",
+ name: "ERC20InvalidApprover",
+ inputs: [
+ {
+ name: "approver",
+ type: "address",
+ internalType: "address",
+ },
+ ],
+ },
+ {
+ type: "error",
+ name: "ERC20InvalidReceiver",
+ inputs: [
+ {
+ name: "receiver",
+ type: "address",
+ internalType: "address",
+ },
+ ],
+ },
+ {
+ type: "error",
+ name: "ERC20InvalidSender",
+ inputs: [
+ {
+ name: "sender",
+ type: "address",
+ internalType: "address",
+ },
+ ],
+ },
+ {
+ type: "error",
+ name: "ERC20InvalidSpender",
+ inputs: [
+ {
+ name: "spender",
+ type: "address",
+ internalType: "address",
+ },
+ ],
},
],
- inheritedFunctions: {},
+ inheritedFunctions: {
+ allowance: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ approve: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ balanceOf: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ decimals: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ name: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ symbol: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ totalSupply: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ transfer: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ transferFrom: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ },
},
- MockToken1: {
- address: "0x906e3a6d1baf80e3e3fa3D57A5DA73099Da86C4c",
+ MockVeBAL: {
+ address: "0xE5A9Ef3838184697602d9c95782304E9b86E230D",
abi: [
{
type: "constructor",
@@ -1106,177 +1080,307 @@ const deployedContracts = {
transferFrom: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
},
},
- MockToken2: {
- address: "0x68c87F9fB214Bb4856a13c9123f9b0624944D1A6",
+ ConstantSumFactory: {
+ address: "0x0EAa0A56CF3260e1999067c174E1f044389C9f5b",
abi: [
{
type: "constructor",
inputs: [
{
- name: "name",
- type: "string",
- internalType: "string",
- },
- {
- name: "symbol",
- type: "string",
- internalType: "string",
+ name: "vault",
+ type: "address",
+ internalType: "contract IVault",
},
{
- name: "initialSupply",
- type: "uint256",
- internalType: "uint256",
+ name: "pauseWindowDuration",
+ type: "uint32",
+ internalType: "uint32",
},
],
stateMutability: "nonpayable",
},
{
type: "function",
- name: "allowance",
+ name: "create",
inputs: [
{
- name: "owner",
- type: "address",
- internalType: "address",
+ name: "name",
+ type: "string",
+ internalType: "string",
},
{
- name: "spender",
- type: "address",
- internalType: "address",
+ name: "symbol",
+ type: "string",
+ internalType: "string",
},
- ],
- outputs: [
{
- name: "",
+ name: "salt",
+ type: "bytes32",
+ internalType: "bytes32",
+ },
+ {
+ name: "tokens",
+ type: "tuple[]",
+ internalType: "struct TokenConfig[]",
+ components: [
+ {
+ name: "token",
+ type: "address",
+ internalType: "contract IERC20",
+ },
+ {
+ name: "tokenType",
+ type: "uint8",
+ internalType: "enum TokenType",
+ },
+ {
+ name: "rateProvider",
+ type: "address",
+ internalType: "contract IRateProvider",
+ },
+ {
+ name: "paysYieldFees",
+ type: "bool",
+ internalType: "bool",
+ },
+ ],
+ },
+ {
+ name: "swapFeePercentage",
type: "uint256",
internalType: "uint256",
},
- ],
- stateMutability: "view",
- },
- {
- type: "function",
- name: "approve",
- inputs: [
{
- name: "spender",
+ name: "protocolFeeExempt",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "roleAccounts",
+ type: "tuple",
+ internalType: "struct PoolRoleAccounts",
+ components: [
+ {
+ name: "pauseManager",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "swapFeeManager",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "poolCreator",
+ type: "address",
+ internalType: "address",
+ },
+ ],
+ },
+ {
+ name: "poolHooksContract",
type: "address",
internalType: "address",
},
{
- name: "value",
- type: "uint256",
- internalType: "uint256",
+ name: "liquidityManagement",
+ type: "tuple",
+ internalType: "struct LiquidityManagement",
+ components: [
+ {
+ name: "disableUnbalancedLiquidity",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableAddLiquidityCustom",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableRemoveLiquidityCustom",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableDonation",
+ type: "bool",
+ internalType: "bool",
+ },
+ ],
},
],
outputs: [
{
- name: "",
- type: "bool",
- internalType: "bool",
+ name: "pool",
+ type: "address",
+ internalType: "address",
},
],
stateMutability: "nonpayable",
},
{
type: "function",
- name: "balanceOf",
+ name: "disable",
+ inputs: [],
+ outputs: [],
+ stateMutability: "nonpayable",
+ },
+ {
+ type: "function",
+ name: "getActionId",
inputs: [
{
- name: "account",
- type: "address",
- internalType: "address",
+ name: "selector",
+ type: "bytes4",
+ internalType: "bytes4",
},
],
outputs: [
{
name: "",
- type: "uint256",
- internalType: "uint256",
+ type: "bytes32",
+ internalType: "bytes32",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "decimals",
+ name: "getAuthorizer",
inputs: [],
outputs: [
{
name: "",
- type: "uint8",
- internalType: "uint8",
+ type: "address",
+ internalType: "contract IAuthorizer",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "mint",
- inputs: [
+ name: "getDefaultLiquidityManagement",
+ inputs: [],
+ outputs: [
{
- name: "amount",
- type: "uint256",
- internalType: "uint256",
+ name: "liquidityManagement",
+ type: "tuple",
+ internalType: "struct LiquidityManagement",
+ components: [
+ {
+ name: "disableUnbalancedLiquidity",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableAddLiquidityCustom",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableRemoveLiquidityCustom",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableDonation",
+ type: "bool",
+ internalType: "bool",
+ },
+ ],
},
],
- outputs: [],
- stateMutability: "nonpayable",
+ stateMutability: "pure",
},
{
type: "function",
- name: "name",
+ name: "getDefaultPoolHooksContract",
inputs: [],
outputs: [
{
name: "",
- type: "string",
- internalType: "string",
+ type: "address",
+ internalType: "address",
+ },
+ ],
+ stateMutability: "pure",
+ },
+ {
+ type: "function",
+ name: "getDeploymentAddress",
+ inputs: [
+ {
+ name: "salt",
+ type: "bytes32",
+ internalType: "bytes32",
+ },
+ ],
+ outputs: [
+ {
+ name: "",
+ type: "address",
+ internalType: "address",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "symbol",
+ name: "getNewPoolPauseWindowEndTime",
inputs: [],
outputs: [
{
name: "",
- type: "string",
- internalType: "string",
+ type: "uint32",
+ internalType: "uint32",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "totalSupply",
+ name: "getOriginalPauseWindowEndTime",
inputs: [],
outputs: [
{
name: "",
- type: "uint256",
- internalType: "uint256",
+ type: "uint32",
+ internalType: "uint32",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "transfer",
- inputs: [
+ name: "getPauseWindowDuration",
+ inputs: [],
+ outputs: [
{
- name: "to",
- type: "address",
- internalType: "address",
+ name: "",
+ type: "uint32",
+ internalType: "uint32",
},
+ ],
+ stateMutability: "view",
+ },
+ {
+ type: "function",
+ name: "getVault",
+ inputs: [],
+ outputs: [
{
- name: "value",
- type: "uint256",
- internalType: "uint256",
+ name: "",
+ type: "address",
+ internalType: "contract IVault",
},
],
+ stateMutability: "view",
+ },
+ {
+ type: "function",
+ name: "isDisabled",
+ inputs: [],
outputs: [
{
name: "",
@@ -1284,27 +1388,17 @@ const deployedContracts = {
internalType: "bool",
},
],
- stateMutability: "nonpayable",
+ stateMutability: "view",
},
{
type: "function",
- name: "transferFrom",
+ name: "isPoolFromFactory",
inputs: [
{
- name: "from",
- type: "address",
- internalType: "address",
- },
- {
- name: "to",
+ name: "pool",
type: "address",
internalType: "address",
},
- {
- name: "value",
- type: "uint256",
- internalType: "uint256",
- },
],
outputs: [
{
@@ -1313,328 +1407,364 @@ const deployedContracts = {
internalType: "bool",
},
],
- stateMutability: "nonpayable",
+ stateMutability: "view",
},
{
type: "event",
- name: "Approval",
+ name: "FactoryDisabled",
+ inputs: [],
+ anonymous: false,
+ },
+ {
+ type: "event",
+ name: "PoolCreated",
inputs: [
{
- name: "owner",
- type: "address",
- indexed: true,
- internalType: "address",
- },
- {
- name: "spender",
+ name: "pool",
type: "address",
indexed: true,
internalType: "address",
},
- {
- name: "value",
- type: "uint256",
- indexed: false,
- internalType: "uint256",
- },
],
anonymous: false,
},
{
- type: "event",
- name: "Transfer",
+ type: "error",
+ name: "Disabled",
+ inputs: [],
+ },
+ {
+ type: "error",
+ name: "PoolPauseWindowDurationOverflow",
+ inputs: [],
+ },
+ {
+ type: "error",
+ name: "SenderNotAllowed",
+ inputs: [],
+ },
+ {
+ type: "error",
+ name: "StandardPoolWithCreator",
+ inputs: [],
+ },
+ ],
+ inheritedFunctions: {
+ disable: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getActionId: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getAuthorizer: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getDefaultLiquidityManagement: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getDefaultPoolHooksContract: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getDeploymentAddress: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getNewPoolPauseWindowEndTime: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getOriginalPauseWindowEndTime: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getPauseWindowDuration: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getVault: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ isDisabled: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ isPoolFromFactory: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ },
+ },
+ ConstantProductFactory: {
+ address: "0xD15Fcc7b91470BDd22a5756B5Add434E9421cea4",
+ abi: [
+ {
+ type: "constructor",
inputs: [
{
- name: "from",
- type: "address",
- indexed: true,
- internalType: "address",
- },
- {
- name: "to",
+ name: "vault",
type: "address",
- indexed: true,
- internalType: "address",
+ internalType: "contract IVault",
},
{
- name: "value",
- type: "uint256",
- indexed: false,
- internalType: "uint256",
+ name: "pauseWindowDuration",
+ type: "uint32",
+ internalType: "uint32",
},
],
- anonymous: false,
+ stateMutability: "nonpayable",
},
{
- type: "error",
- name: "ERC20InsufficientAllowance",
+ type: "function",
+ name: "create",
inputs: [
{
- name: "spender",
- type: "address",
- internalType: "address",
+ name: "name",
+ type: "string",
+ internalType: "string",
},
{
- name: "allowance",
- type: "uint256",
- internalType: "uint256",
+ name: "symbol",
+ type: "string",
+ internalType: "string",
},
{
- name: "needed",
- type: "uint256",
- internalType: "uint256",
+ name: "salt",
+ type: "bytes32",
+ internalType: "bytes32",
},
- ],
- },
- {
- type: "error",
- name: "ERC20InsufficientBalance",
- inputs: [
{
- name: "sender",
- type: "address",
- internalType: "address",
+ name: "tokens",
+ type: "tuple[]",
+ internalType: "struct TokenConfig[]",
+ components: [
+ {
+ name: "token",
+ type: "address",
+ internalType: "contract IERC20",
+ },
+ {
+ name: "tokenType",
+ type: "uint8",
+ internalType: "enum TokenType",
+ },
+ {
+ name: "rateProvider",
+ type: "address",
+ internalType: "contract IRateProvider",
+ },
+ {
+ name: "paysYieldFees",
+ type: "bool",
+ internalType: "bool",
+ },
+ ],
},
{
- name: "balance",
+ name: "swapFeePercentage",
type: "uint256",
internalType: "uint256",
},
{
- name: "needed",
- type: "uint256",
- internalType: "uint256",
+ name: "protocolFeeExempt",
+ type: "bool",
+ internalType: "bool",
},
- ],
- },
- {
- type: "error",
- name: "ERC20InvalidApprover",
- inputs: [
{
- name: "approver",
+ name: "roleAccounts",
+ type: "tuple",
+ internalType: "struct PoolRoleAccounts",
+ components: [
+ {
+ name: "pauseManager",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "swapFeeManager",
+ type: "address",
+ internalType: "address",
+ },
+ {
+ name: "poolCreator",
+ type: "address",
+ internalType: "address",
+ },
+ ],
+ },
+ {
+ name: "poolHooksContract",
type: "address",
internalType: "address",
},
+ {
+ name: "liquidityManagement",
+ type: "tuple",
+ internalType: "struct LiquidityManagement",
+ components: [
+ {
+ name: "disableUnbalancedLiquidity",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableAddLiquidityCustom",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableRemoveLiquidityCustom",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableDonation",
+ type: "bool",
+ internalType: "bool",
+ },
+ ],
+ },
],
- },
- {
- type: "error",
- name: "ERC20InvalidReceiver",
- inputs: [
+ outputs: [
{
- name: "receiver",
+ name: "pool",
type: "address",
internalType: "address",
},
],
+ stateMutability: "nonpayable",
},
{
- type: "error",
- name: "ERC20InvalidSender",
+ type: "function",
+ name: "disable",
+ inputs: [],
+ outputs: [],
+ stateMutability: "nonpayable",
+ },
+ {
+ type: "function",
+ name: "getActionId",
inputs: [
{
- name: "sender",
- type: "address",
- internalType: "address",
+ name: "selector",
+ type: "bytes4",
+ internalType: "bytes4",
},
],
+ outputs: [
+ {
+ name: "",
+ type: "bytes32",
+ internalType: "bytes32",
+ },
+ ],
+ stateMutability: "view",
},
{
- type: "error",
- name: "ERC20InvalidSpender",
- inputs: [
+ type: "function",
+ name: "getAuthorizer",
+ inputs: [],
+ outputs: [
{
- name: "spender",
+ name: "",
type: "address",
- internalType: "address",
+ internalType: "contract IAuthorizer",
},
],
+ stateMutability: "view",
},
- ],
- inheritedFunctions: {
- allowance: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- approve: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- balanceOf: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- decimals: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- name: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- symbol: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- totalSupply: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- transfer: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- transferFrom: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- },
- },
- MockVeBAL: {
- address: "0xBcd2152CD06E3e65f88f3f21aeBDc5473d8EAef4",
- abi: [
{
- type: "constructor",
- inputs: [
- {
- name: "name",
- type: "string",
- internalType: "string",
- },
- {
- name: "symbol",
- type: "string",
- internalType: "string",
- },
+ type: "function",
+ name: "getDefaultLiquidityManagement",
+ inputs: [],
+ outputs: [
{
- name: "initialSupply",
- type: "uint256",
- internalType: "uint256",
+ name: "liquidityManagement",
+ type: "tuple",
+ internalType: "struct LiquidityManagement",
+ components: [
+ {
+ name: "disableUnbalancedLiquidity",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableAddLiquidityCustom",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableRemoveLiquidityCustom",
+ type: "bool",
+ internalType: "bool",
+ },
+ {
+ name: "enableDonation",
+ type: "bool",
+ internalType: "bool",
+ },
+ ],
},
],
- stateMutability: "nonpayable",
+ stateMutability: "pure",
},
{
type: "function",
- name: "allowance",
- inputs: [
- {
- name: "owner",
- type: "address",
- internalType: "address",
- },
- {
- name: "spender",
- type: "address",
- internalType: "address",
- },
- ],
+ name: "getDefaultPoolHooksContract",
+ inputs: [],
outputs: [
{
name: "",
- type: "uint256",
- internalType: "uint256",
- },
- ],
- stateMutability: "view",
- },
- {
- type: "function",
- name: "approve",
- inputs: [
- {
- name: "spender",
type: "address",
internalType: "address",
},
- {
- name: "value",
- type: "uint256",
- internalType: "uint256",
- },
- ],
- outputs: [
- {
- name: "",
- type: "bool",
- internalType: "bool",
- },
],
- stateMutability: "nonpayable",
+ stateMutability: "pure",
},
{
type: "function",
- name: "balanceOf",
+ name: "getDeploymentAddress",
inputs: [
{
- name: "account",
- type: "address",
- internalType: "address",
+ name: "salt",
+ type: "bytes32",
+ internalType: "bytes32",
},
],
outputs: [
{
name: "",
- type: "uint256",
- internalType: "uint256",
+ type: "address",
+ internalType: "address",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "decimals",
+ name: "getNewPoolPauseWindowEndTime",
inputs: [],
outputs: [
{
name: "",
- type: "uint8",
- internalType: "uint8",
+ type: "uint32",
+ internalType: "uint32",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "mint",
- inputs: [
- {
- name: "amount",
- type: "uint256",
- internalType: "uint256",
- },
- ],
- outputs: [],
- stateMutability: "nonpayable",
- },
- {
- type: "function",
- name: "name",
+ name: "getOriginalPauseWindowEndTime",
inputs: [],
outputs: [
{
name: "",
- type: "string",
- internalType: "string",
+ type: "uint32",
+ internalType: "uint32",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "symbol",
+ name: "getPauseWindowDuration",
inputs: [],
outputs: [
{
name: "",
- type: "string",
- internalType: "string",
+ type: "uint32",
+ internalType: "uint32",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "totalSupply",
+ name: "getVault",
inputs: [],
outputs: [
{
name: "",
- type: "uint256",
- internalType: "uint256",
+ type: "address",
+ internalType: "contract IVault",
},
],
stateMutability: "view",
},
{
type: "function",
- name: "transfer",
- inputs: [
- {
- name: "to",
- type: "address",
- internalType: "address",
- },
- {
- name: "value",
- type: "uint256",
- internalType: "uint256",
- },
- ],
+ name: "isDisabled",
+ inputs: [],
outputs: [
{
name: "",
@@ -1642,27 +1772,17 @@ const deployedContracts = {
internalType: "bool",
},
],
- stateMutability: "nonpayable",
+ stateMutability: "view",
},
{
type: "function",
- name: "transferFrom",
+ name: "isPoolFromFactory",
inputs: [
{
- name: "from",
- type: "address",
- internalType: "address",
- },
- {
- name: "to",
+ name: "pool",
type: "address",
internalType: "address",
},
- {
- name: "value",
- type: "uint256",
- internalType: "uint256",
- },
],
outputs: [
{
@@ -1671,159 +1791,65 @@ const deployedContracts = {
internalType: "bool",
},
],
- stateMutability: "nonpayable",
+ stateMutability: "view",
},
{
type: "event",
- name: "Approval",
- inputs: [
- {
- name: "owner",
- type: "address",
- indexed: true,
- internalType: "address",
- },
- {
- name: "spender",
- type: "address",
- indexed: true,
- internalType: "address",
- },
- {
- name: "value",
- type: "uint256",
- indexed: false,
- internalType: "uint256",
- },
- ],
+ name: "FactoryDisabled",
+ inputs: [],
anonymous: false,
},
{
type: "event",
- name: "Transfer",
+ name: "PoolCreated",
inputs: [
{
- name: "from",
- type: "address",
- indexed: true,
- internalType: "address",
- },
- {
- name: "to",
+ name: "pool",
type: "address",
indexed: true,
internalType: "address",
},
- {
- name: "value",
- type: "uint256",
- indexed: false,
- internalType: "uint256",
- },
],
anonymous: false,
},
{
type: "error",
- name: "ERC20InsufficientAllowance",
- inputs: [
- {
- name: "spender",
- type: "address",
- internalType: "address",
- },
- {
- name: "allowance",
- type: "uint256",
- internalType: "uint256",
- },
- {
- name: "needed",
- type: "uint256",
- internalType: "uint256",
- },
- ],
- },
- {
- type: "error",
- name: "ERC20InsufficientBalance",
- inputs: [
- {
- name: "sender",
- type: "address",
- internalType: "address",
- },
- {
- name: "balance",
- type: "uint256",
- internalType: "uint256",
- },
- {
- name: "needed",
- type: "uint256",
- internalType: "uint256",
- },
- ],
- },
- {
- type: "error",
- name: "ERC20InvalidApprover",
- inputs: [
- {
- name: "approver",
- type: "address",
- internalType: "address",
- },
- ],
+ name: "Disabled",
+ inputs: [],
},
{
type: "error",
- name: "ERC20InvalidReceiver",
- inputs: [
- {
- name: "receiver",
- type: "address",
- internalType: "address",
- },
- ],
+ name: "PoolPauseWindowDurationOverflow",
+ inputs: [],
},
{
type: "error",
- name: "ERC20InvalidSender",
- inputs: [
- {
- name: "sender",
- type: "address",
- internalType: "address",
- },
- ],
+ name: "SenderNotAllowed",
+ inputs: [],
},
{
type: "error",
- name: "ERC20InvalidSpender",
- inputs: [
- {
- name: "spender",
- type: "address",
- internalType: "address",
- },
- ],
+ name: "StandardPoolWithCreator",
+ inputs: [],
},
],
inheritedFunctions: {
- allowance: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- approve: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- balanceOf: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- decimals: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- name: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- symbol: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- totalSupply: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- transfer: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
- transferFrom: "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol",
+ disable: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getActionId: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getAuthorizer: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getDefaultLiquidityManagement: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getDefaultPoolHooksContract: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getDeploymentAddress: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getNewPoolPauseWindowEndTime: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getOriginalPauseWindowEndTime: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getPauseWindowDuration: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ getVault: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ isDisabled: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
+ isPoolFromFactory: "lib/balancer-v3-monorepo/pkg/pool-utils/contracts/BasePoolFactory.sol",
},
},
VeBALFeeDiscountHook: {
- address: "0x0A6338Be5da861e4F864C2B4a8dC219C2A20AA27",
+ address: "0xd3d3399b02b8Bde3b4A77295393679d95C380f10",
abi: [
{
type: "constructor",
From 0d6a157682a289cef4bfe103262945f377723490 Mon Sep 17 00:00:00 2001
From: Matthew Pereira
Date: Mon, 22 Jul 2024 15:22:08 -0700
Subject: [PATCH 2/7] Improve comments and script names
---
packages/foundry/script/Deploy.s.sol | 21 ++++++++-----------
...Pool.s.sol => DeployConstantProduct.s.sol} | 11 +++++-----
...tSumPool.s.sol => DeployConstantSum.s.sol} | 7 +++----
.../foundry/script/DeployMockTokens.s.sol | 3 +--
4 files changed, 18 insertions(+), 24 deletions(-)
rename packages/foundry/script/{DeployConstantProductPool.s.sol => DeployConstantProduct.s.sol} (93%)
rename packages/foundry/script/{DeployConstantSumPool.s.sol => DeployConstantSum.s.sol} (96%)
diff --git a/packages/foundry/script/Deploy.s.sol b/packages/foundry/script/Deploy.s.sol
index 38d543ba..7dd86dea 100644
--- a/packages/foundry/script/Deploy.s.sol
+++ b/packages/foundry/script/Deploy.s.sol
@@ -1,30 +1,27 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
-// import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
-import { PoolHelpers } from "./PoolHelpers.sol";
-import { ScaffoldHelpers } from "./ScaffoldHelpers.sol";
import { DeployMockTokens } from "./DeployMockTokens.s.sol";
-import { DeployConstantSumPool } from "./DeployConstantSumPool.s.sol";
-import { DeployConstantProductPool } from "./DeployConstantProductPool.s.sol";
+import { DeployConstantSum } from "./DeployConstantSum.s.sol";
+import { DeployConstantProduct } from "./DeployConstantProduct.s.sol";
/**
* @title Deploy Script
- * @notice Deploys mock tokens, a constant sum pool, and a constant product pool
+ * @notice Import all deploy scripts here so that scaffold can exportDeployments()
* @dev Run this script with `yarn deploy`
*/
-contract DeployScript is DeployMockTokens, DeployConstantSumPool, DeployConstantProductPool {
+contract DeployScript is DeployMockTokens, DeployConstantSum, DeployConstantProduct {
function run() external virtual {
- // Deploy the mock tokens
+ // Deploy mock tokens to be used for pools and hooks contracts
(IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) = deployMockTokens();
- // Deploy a constant sum factory pool
- deployConstantSumPool(mockToken1, mockToken2);
+ // Deploy a constant sum factory and a pool
+ deployConstantSum(mockToken1, mockToken2);
- // Deploy a constant product pool
- deployConstantProductPool(mockToken1, mockToken2, mockVeBAL);
+ // Deploy a constant product factory, a hooks contract, and a pool
+ deployConstantProduct(mockToken1, mockToken2, mockVeBAL);
/**
* This function generates the file containing the contracts Abi definitions that are carried from /foundry to /nextjs.
diff --git a/packages/foundry/script/DeployConstantProductPool.s.sol b/packages/foundry/script/DeployConstantProduct.s.sol
similarity index 93%
rename from packages/foundry/script/DeployConstantProductPool.s.sol
rename to packages/foundry/script/DeployConstantProduct.s.sol
index e3b625a0..de5da367 100644
--- a/packages/foundry/script/DeployConstantProductPool.s.sol
+++ b/packages/foundry/script/DeployConstantProduct.s.sol
@@ -11,7 +11,6 @@ import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
import { IRateProvider } from "@balancer-labs/v3-interfaces/contracts/vault/IRateProvider.sol";
import { InputHelpers } from "@balancer-labs/v3-solidity-utils/contracts/helpers/InputHelpers.sol";
import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
-import { DevOpsTools } from "lib/foundry-devops/src/DevOpsTools.sol";
import { PoolHelpers } from "./PoolHelpers.sol";
import { ScaffoldHelpers, console } from "./ScaffoldHelpers.sol";
@@ -19,11 +18,11 @@ import { VeBALFeeDiscountHook } from "../contracts/hooks/VeBALFeeDiscountHook.so
import { ConstantProductFactory } from "../contracts/pools/ConstantProductFactory.sol";
/**
- * @title Deploy Constant Product Pool
- * @notice Deploys a factory and hooks contract before deploying, registering, and initializing a Constant Product Pool
+ * @title Deploy Constant Product
+ * @notice Deploys a factory and hooks contract and then deploys, registers, and initializes a constant product pool
*/
-contract DeployConstantProductPool is PoolHelpers, ScaffoldHelpers {
- function deployConstantProductPool(IERC20 token1, IERC20 token2, IERC20 veBAL) internal {
+contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
+ function deployConstantProduct(IERC20 token1, IERC20 token2, IERC20 veBAL) internal {
// Set the deployment configurations
uint32 pauseWindowDuration = 365 days;
RegistrationConfig memory regConfig = getPoolRegistrationConfig(token1, token2);
@@ -37,7 +36,7 @@ contract DeployConstantProductPool is PoolHelpers, ScaffoldHelpers {
ConstantProductFactory factory = new ConstantProductFactory(IVault(vault), pauseWindowDuration);
console.log("Constant Product Factory deployed at: %s", address(factory));
- // Deploy a hooks contract that permits pools created by the Constant Product factory
+ // Deploy a hooks contract
VeBALFeeDiscountHook poolHooksContract = new VeBALFeeDiscountHook(
IVault(vault),
address(factory),
diff --git a/packages/foundry/script/DeployConstantSumPool.s.sol b/packages/foundry/script/DeployConstantSum.s.sol
similarity index 96%
rename from packages/foundry/script/DeployConstantSumPool.s.sol
rename to packages/foundry/script/DeployConstantSum.s.sol
index 920b5506..686f2ed2 100644
--- a/packages/foundry/script/DeployConstantSumPool.s.sol
+++ b/packages/foundry/script/DeployConstantSum.s.sol
@@ -11,18 +11,17 @@ import { IRateProvider } from "@balancer-labs/v3-interfaces/contracts/vault/IRat
import { InputHelpers } from "@balancer-labs/v3-solidity-utils/contracts/helpers/InputHelpers.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
-import { DevOpsTools } from "lib/foundry-devops/src/DevOpsTools.sol";
import { PoolHelpers } from "./PoolHelpers.sol";
import { ScaffoldHelpers, console } from "./ScaffoldHelpers.sol";
import { ConstantSumFactory } from "../contracts/pools/ConstantSumFactory.sol";
/**
- * @title Deploy Constant Sum Pool
+ * @title Deploy Constant Sum
* @notice Deploys, registers, and initializes a Constant Sum Pool
*/
-contract DeployConstantSumPool is PoolHelpers, ScaffoldHelpers {
- function deployConstantSumPool(IERC20 token1, IERC20 token2) internal {
+contract DeployConstantSum is PoolHelpers, ScaffoldHelpers {
+ function deployConstantSum(IERC20 token1, IERC20 token2) internal {
// Set the deployment configurations
uint32 pauseWindowDuration = 365 days;
RegistrationConfig memory regConfig = getRegistrationConfig(token1, token2);
diff --git a/packages/foundry/script/DeployMockTokens.s.sol b/packages/foundry/script/DeployMockTokens.s.sol
index ba09e64a..4e58bb76 100644
--- a/packages/foundry/script/DeployMockTokens.s.sol
+++ b/packages/foundry/script/DeployMockTokens.s.sol
@@ -4,7 +4,6 @@ pragma solidity ^0.8.24;
import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
-import { PoolHelpers } from "./PoolHelpers.sol";
import { ScaffoldHelpers, console } from "./ScaffoldHelpers.sol";
import { MockToken1 } from "../contracts/mocks/MockToken1.sol";
import { MockToken2 } from "../contracts/mocks/MockToken2.sol";
@@ -14,7 +13,7 @@ import { MockVeBAL } from "../contracts/mocks/MockVeBAL.sol";
* @title Deploy Mock Tokens
* @notice Deploys mock tokens for use with pools and hooks
*/
-contract DeployMockTokens is PoolHelpers, ScaffoldHelpers {
+contract DeployMockTokens is ScaffoldHelpers {
function deployMockTokens() internal returns (IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) {
uint256 deployerPrivateKey = getDeployerPrivateKey();
From d1db3c5cd0dfe90125a6966c52a1d101c6b2fd68 Mon Sep 17 00:00:00 2001
From: Matthew Pereira
Date: Mon, 22 Jul 2024 17:25:51 -0700
Subject: [PATCH 3/7] simplyify mock token contract comments
---
.../foundry/contracts/hooks/VeBALFeeDiscountHook.sol | 3 ++-
packages/foundry/contracts/mocks/MockToken1.sol | 11 ++---------
packages/foundry/contracts/mocks/MockToken2.sol | 11 ++---------
packages/foundry/contracts/mocks/MockVeBAL.sol | 11 ++---------
packages/nextjs/contracts/deployedContracts.ts | 12 ++++++------
5 files changed, 14 insertions(+), 34 deletions(-)
diff --git a/packages/foundry/contracts/hooks/VeBALFeeDiscountHook.sol b/packages/foundry/contracts/hooks/VeBALFeeDiscountHook.sol
index 1f0e9c61..806d9c1e 100644
--- a/packages/foundry/contracts/hooks/VeBALFeeDiscountHook.sol
+++ b/packages/foundry/contracts/hooks/VeBALFeeDiscountHook.sol
@@ -15,7 +15,8 @@ import { IRouterCommon } from "@balancer-labs/v3-interfaces/contracts/vault/IRou
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/**
- * @title VeBAL Fee Discount Hook Example
+ * @title VeBAL Fee Discount Hook
+ * @notice Applies a 50% discount to the swap fee for users holding veBAL tokens
*/
contract VeBALFeeDiscountHook is BaseHooks {
// only pools from the allowedFactory are able to register and use this hook
diff --git a/packages/foundry/contracts/mocks/MockToken1.sol b/packages/foundry/contracts/mocks/MockToken1.sol
index ed3776c2..9bf86226 100644
--- a/packages/foundry/contracts/mocks/MockToken1.sol
+++ b/packages/foundry/contracts/mocks/MockToken1.sol
@@ -3,20 +3,13 @@ pragma solidity ^0.8.24;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
-/**
- * @title Mock Token 1
- * @notice Entire initial supply is minted to the deployer
- * @dev Default decimals is 18, but you can override the decimals function from ERC20
- */
contract MockToken1 is ERC20 {
+ // Mint the initial supply to the deployer
constructor(string memory name, string memory symbol, uint256 initialSupply) ERC20(name, symbol) {
_mint(msg.sender, initialSupply);
}
- /**
- * Allow any user to mint any amount of tokens to their wallet
- * This function is accessible on the frontend's "Debug" page
- */
+ // Allow any user to mint any amount of tokens to their wallet
function mint(uint256 amount) external {
_mint(msg.sender, amount);
}
diff --git a/packages/foundry/contracts/mocks/MockToken2.sol b/packages/foundry/contracts/mocks/MockToken2.sol
index 1264bcf3..3474d914 100644
--- a/packages/foundry/contracts/mocks/MockToken2.sol
+++ b/packages/foundry/contracts/mocks/MockToken2.sol
@@ -3,20 +3,13 @@ pragma solidity ^0.8.24;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
-/**
- * @title Mock Token 2
- * @notice Entire initial supply is minted to the deployer
- * @dev Default decimals is 18, but you can override the decimals function from ERC20
- */
contract MockToken2 is ERC20 {
+ // Mint the initial supply to the deployer
constructor(string memory name, string memory symbol, uint256 initialSupply) ERC20(name, symbol) {
_mint(msg.sender, initialSupply);
}
- /**
- * Allow any user to mint any amount of tokens to their wallet
- * This function is accessible on the frontend's "Debug" page
- */
+ // Allow any user to mint any amount of tokens to their wallet
function mint(uint256 amount) external {
_mint(msg.sender, amount);
}
diff --git a/packages/foundry/contracts/mocks/MockVeBAL.sol b/packages/foundry/contracts/mocks/MockVeBAL.sol
index 832666ee..107a5bd8 100644
--- a/packages/foundry/contracts/mocks/MockVeBAL.sol
+++ b/packages/foundry/contracts/mocks/MockVeBAL.sol
@@ -3,20 +3,13 @@ pragma solidity ^0.8.24;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
-/**
- * @title Mock VeBAL
- * @notice Entire initial supply is minted to the deployer
- * @dev Default decimals is 18, but you can override the decimals function from ERC20
- */
contract MockVeBAL is ERC20 {
+ // Mint the initial supply to the deployer
constructor(string memory name, string memory symbol, uint256 initialSupply) ERC20(name, symbol) {
_mint(msg.sender, initialSupply);
}
- /**
- * Allow any user to mint any amount of tokens to their wallet
- * This function is accessible on the frontend's "Debug" page
- */
+ // Allow any user to mint any amount of tokens to their wallet
function mint(uint256 amount) external {
_mint(msg.sender, amount);
}
diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts
index 7c65c0a5..c513effa 100644
--- a/packages/nextjs/contracts/deployedContracts.ts
+++ b/packages/nextjs/contracts/deployedContracts.ts
@@ -7,7 +7,7 @@ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";
const deployedContracts = {
31337: {
MockToken1: {
- address: "0x539383fDc37eE70495088826ec32F6B28153245C",
+ address: "0x8e8cB505973E04200554Bd98741086C7Eca9f42a",
abi: [
{
type: "constructor",
@@ -365,7 +365,7 @@ const deployedContracts = {
},
},
MockToken2: {
- address: "0x69d2485148F2F6e408db39C2516D948Ac1CD69Ab",
+ address: "0xC2D1A7c03C0459a8d0Ee885283CE828DE5fFf617",
abi: [
{
type: "constructor",
@@ -723,7 +723,7 @@ const deployedContracts = {
},
},
MockVeBAL: {
- address: "0xE5A9Ef3838184697602d9c95782304E9b86E230D",
+ address: "0x906e3a6d1baf80e3e3fa3D57A5DA73099Da86C4c",
abi: [
{
type: "constructor",
@@ -1081,7 +1081,7 @@ const deployedContracts = {
},
},
ConstantSumFactory: {
- address: "0x0EAa0A56CF3260e1999067c174E1f044389C9f5b",
+ address: "0x68c87F9fB214Bb4856a13c9123f9b0624944D1A6",
abi: [
{
type: "constructor",
@@ -1465,7 +1465,7 @@ const deployedContracts = {
},
},
ConstantProductFactory: {
- address: "0xD15Fcc7b91470BDd22a5756B5Add434E9421cea4",
+ address: "0x2a374E85Ca5F1af906De5CdDa3658219e8759097",
abi: [
{
type: "constructor",
@@ -1849,7 +1849,7 @@ const deployedContracts = {
},
},
VeBALFeeDiscountHook: {
- address: "0xd3d3399b02b8Bde3b4A77295393679d95C380f10",
+ address: "0xb33ca895101aB93835fd846d8C23FBdBC29d5843",
abi: [
{
type: "constructor",
From 0bca6e3817785cff6f859dad0fe5b54321b5f3c5 Mon Sep 17 00:00:00 2001
From: Matthew Pereira
Date: Thu, 25 Jul 2024 15:10:35 -0700
Subject: [PATCH 4/7] Update deploy scripts to be more consistent and readable
---
.../contracts/hooks/VeBALFeeDiscountHook.sol | 54 ++++++++++++-------
packages/foundry/script/Deploy.s.sol | 15 +++---
.../script/DeployConstantProduct.s.sol | 31 ++++++-----
.../foundry/script/DeployConstantSum.s.sol | 29 +++++-----
.../foundry/script/DeployMockTokens.s.sol | 2 +-
packages/foundry/script/PoolHelpers.sol | 38 ++++---------
.../foundry/test/VeBALFeeDiscountHook.t.sol | 3 +-
.../nextjs/contracts/deployedContracts.ts | 24 +++------
8 files changed, 99 insertions(+), 97 deletions(-)
diff --git a/packages/foundry/contracts/hooks/VeBALFeeDiscountHook.sol b/packages/foundry/contracts/hooks/VeBALFeeDiscountHook.sol
index 806d9c1e..3ce87035 100644
--- a/packages/foundry/contracts/hooks/VeBALFeeDiscountHook.sol
+++ b/packages/foundry/contracts/hooks/VeBALFeeDiscountHook.sol
@@ -9,8 +9,8 @@ import {
TokenConfig,
LiquidityManagement
} from "@balancer-labs/v3-vault/contracts/BaseHooks.sol";
-import { IBasePoolFactory } from "@balancer-labs/v3-interfaces/contracts/vault/IBasePoolFactory.sol";
import { IBasePool } from "@balancer-labs/v3-interfaces/contracts/vault/IBasePool.sol";
+import { IBasePoolFactory } from "@balancer-labs/v3-interfaces/contracts/vault/IBasePoolFactory.sol";
import { IRouterCommon } from "@balancer-labs/v3-interfaces/contracts/vault/IRouterCommon.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
@@ -19,54 +19,70 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
* @notice Applies a 50% discount to the swap fee for users holding veBAL tokens
*/
contract VeBALFeeDiscountHook is BaseHooks {
- // only pools from the allowedFactory are able to register and use this hook
address private immutable _allowedFactory;
- // only calls from a trusted routers are allowed to call this hook, because the hook relies on the getSender
- // implementation to work properly
address private immutable _trustedRouter;
IERC20 private immutable _veBAL;
- constructor(IVault vault, address allowedFactory, address veBAL, address trustedRouter) BaseHooks(vault) {
+ constructor(IVault vault, address allowedFactory, address trustedRouter, IERC20 veBAL) BaseHooks(vault) {
_allowedFactory = allowedFactory;
_trustedRouter = trustedRouter;
- _veBAL = IERC20(veBAL);
- }
-
- /// @inheritdoc IHooks
- function getHookFlags() external pure override returns (IHooks.HookFlags memory hookFlags) {
- hookFlags.shouldCallComputeDynamicSwapFee = true;
+ _veBAL = veBAL;
}
- /// @inheritdoc IHooks
+ /**
+ * @notice Hook executed when pool is registered
+ * @dev Return true if registration was successful
+ * @dev Return false to revert the registration of the pool
+ * @dev Vault address can be accessed with msg.sender
+ * @param factory Address of the pool factory
+ * @param pool Address of the pool
+ * @return success True if the hook allowed the registration, false otherwise
+ */
function onRegister(
address factory,
address pool,
TokenConfig[] memory,
LiquidityManagement calldata
) external view override returns (bool) {
- // This hook implements a restrictive approach, where we check if the factory is an allowed factory and if
- // the pool was created by the allowed factory. Since we only use onComputeDynamicSwapFee, this might be an
- // overkill in real applications because the pool math doesn't play a role in the discount calculation.
+ // Only pools deployed by an allowed factory may register
return factory == _allowedFactory && IBasePoolFactory(factory).isPoolFromFactory(pool);
}
+ /**
+ * @notice Returns flags informing which hooks are implemented in the contract.
+ * @return hookFlags Flags indicating which hooks the contract supports
+ */
+ function getHookFlags() external pure override returns (IHooks.HookFlags memory hookFlags) {
+ // Support the `onComputeDynamicSwapFeePercentage` hook
+ hookFlags.shouldCallComputeDynamicSwapFee = true;
+ }
+
+ /**
+ * @notice Called before `onBeforeSwap` if the pool has dynamic fees.
+ * @param params Swap parameters (see IBasePool.PoolSwapParams for struct definition)
+ * @param staticSwapFeePercentage Value of the static swap fee, for reference
+ * @return success True if the pool wishes to proceed with settlement
+ * @return dynamicSwapFee Value of the swap fee
+ */
function onComputeDynamicSwapFee(
IBasePool.PoolSwapParams calldata params,
- address,
+ address, // pool
uint256 staticSwapFeePercentage
- ) external view override returns (bool, uint256) {
- // If the router is not trusted, does not apply the veBAL discount because getSender() may be manipulated by a malicious router.
+ ) external view override returns (bool success, uint256 dynamicSwapFee) {
+ // If the router is not trusted, do not apply a fee discount
if (params.router != _trustedRouter) {
return (true, staticSwapFeePercentage);
}
+ // Find the user's address
address user = IRouterCommon(params.router).getSender();
- // If user has veBAL, apply a 50% discount to the current fee (divides fees by 2)
+ // If the user owns veBAL, apply a 50% discount to the swap fee
if (_veBAL.balanceOf(user) > 0) {
return (true, staticSwapFeePercentage / 2);
}
+ // Otherwise, do not apply the discount
return (true, staticSwapFeePercentage);
}
}
diff --git a/packages/foundry/script/Deploy.s.sol b/packages/foundry/script/Deploy.s.sol
index 7dd86dea..1f7d1433 100644
--- a/packages/foundry/script/Deploy.s.sol
+++ b/packages/foundry/script/Deploy.s.sol
@@ -1,27 +1,30 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
-import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
-
+import { ScaffoldHelpers } from "./ScaffoldHelpers.sol";
import { DeployMockTokens } from "./DeployMockTokens.s.sol";
import { DeployConstantSum } from "./DeployConstantSum.s.sol";
import { DeployConstantProduct } from "./DeployConstantProduct.s.sol";
+import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
/**
* @title Deploy Script
* @notice Import all deploy scripts here so that scaffold can exportDeployments()
* @dev Run this script with `yarn deploy`
*/
-contract DeployScript is DeployMockTokens, DeployConstantSum, DeployConstantProduct {
+contract DeployScript is ScaffoldHelpers {
function run() external virtual {
// Deploy mock tokens to be used for pools and hooks contracts
- (IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) = deployMockTokens();
+ DeployMockTokens deployMockTokens = new DeployMockTokens();
+ (IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) = deployMockTokens.run();
// Deploy a constant sum factory and a pool
- deployConstantSum(mockToken1, mockToken2);
+ DeployConstantSum deployConstantSum = new DeployConstantSum();
+ deployConstantSum.run(mockToken1, mockToken2);
// Deploy a constant product factory, a hooks contract, and a pool
- deployConstantProduct(mockToken1, mockToken2, mockVeBAL);
+ DeployConstantProduct deployConstantProduct = new DeployConstantProduct();
+ deployConstantProduct.run(mockToken1, mockToken2, mockVeBAL);
/**
* This function generates the file containing the contracts Abi definitions that are carried from /foundry to /nextjs.
diff --git a/packages/foundry/script/DeployConstantProduct.s.sol b/packages/foundry/script/DeployConstantProduct.s.sol
index de5da367..c4908915 100644
--- a/packages/foundry/script/DeployConstantProduct.s.sol
+++ b/packages/foundry/script/DeployConstantProduct.s.sol
@@ -22,11 +22,11 @@ import { ConstantProductFactory } from "../contracts/pools/ConstantProductFactor
* @notice Deploys a factory and hooks contract and then deploys, registers, and initializes a constant product pool
*/
contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
- function deployConstantProduct(IERC20 token1, IERC20 token2, IERC20 veBAL) internal {
+ function run(IERC20 token1, IERC20 token2, IERC20 veBAL) external virtual {
// Set the deployment configurations
uint32 pauseWindowDuration = 365 days;
- RegistrationConfig memory regConfig = getPoolRegistrationConfig(token1, token2);
- InitializationConfig memory initConfig = getPoolInitializationConfig(token1, token2);
+ PoolRegistrationConfig memory regConfig = getPoolRegistrationConfig(token1, token2);
+ PoolInitializationConfig memory initConfig = getPoolInitializationConfig(token1, token2);
// Start creating the transactions
uint256 deployerPrivateKey = getDeployerPrivateKey();
@@ -40,8 +40,8 @@ contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
VeBALFeeDiscountHook poolHooksContract = new VeBALFeeDiscountHook(
IVault(vault),
address(factory),
- address(veBAL),
- address(router)
+ address(router),
+ IERC20(veBAL)
);
console.log("VeBALFeeDiscountHook deployed at address: %s", address(poolHooksContract));
@@ -59,8 +59,14 @@ contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
);
console.log("Constant Product Pool deployed at: %s", pool);
+ // Approve Permit2 contract to spend tokens on behalf of deployer
+ approveSpenderOnToken(address(permit2), initConfig.tokens);
+
+ // Approve Router contract to spend tokens using Permit2
+ approveSpenderOnPermit2(address(router), initConfig.tokens);
+
// Seed the pool with initial liquidity
- initializePool(
+ router.initialize(
pool,
initConfig.tokens,
initConfig.exactAmountsIn,
@@ -74,15 +80,14 @@ contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
/**
* @dev Set all of the configurations for deploying and registering a pool here
- *
- * TokenConfig encapsulates the data required for the Vault to support a token of the given type.
+ * @notice TokenConfig encapsulates the data required for the Vault to support a token of the given type.
* For STANDARD tokens, the rate provider address must be 0, and paysYieldFees must be false.
* All WITH_RATE tokens need a rate provider, and may or may not be yield-bearing.
*/
function getPoolRegistrationConfig(
IERC20 token1,
IERC20 token2
- ) internal view returns (RegistrationConfig memory regConfig) {
+ ) internal view returns (PoolRegistrationConfig memory config) {
string memory name = "Constant Product Pool"; // name for the pool
string memory symbol = "CPP"; // symbol for the BPT
bytes32 salt = keccak256(abi.encode(block.number)); // salt for the pool deployment via factory
@@ -90,7 +95,7 @@ contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
bool protocolFeeExempt = false;
address poolHooksContract = address(0); // zero address if no hooks contract is needed
- TokenConfig[] memory tokenConfig = new TokenConfig[](2); // An array of descriptors for the tokens the pool will manage.
+ TokenConfig[] memory tokenConfig = new TokenConfig[](2); // An array of descriptors for the tokens the pool will manage
tokenConfig[0] = TokenConfig({ // Make sure to have proper token order (alphanumeric)
token: token1,
tokenType: TokenType.STANDARD, // STANDARD or WITH_RATE
@@ -116,7 +121,7 @@ contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
enableDonation: false
});
- regConfig = RegistrationConfig({
+ config = PoolRegistrationConfig({
name: name,
symbol: symbol,
salt: salt,
@@ -136,7 +141,7 @@ contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
function getPoolInitializationConfig(
IERC20 token1,
IERC20 token2
- ) internal pure returns (InitializationConfig memory poolInitConfig) {
+ ) internal pure returns (PoolInitializationConfig memory config) {
IERC20[] memory tokens = new IERC20[](2); // Array of tokens to be used in the pool
tokens[0] = token1;
tokens[1] = token2;
@@ -147,7 +152,7 @@ contract DeployConstantProduct is PoolHelpers, ScaffoldHelpers {
bool wethIsEth = false; // If true, incoming ETH will be wrapped to WETH; otherwise the Vault will pull WETH tokens
bytes memory userData = bytes(""); // Additional (optional) data required for adding initial liquidity
- poolInitConfig = InitializationConfig({
+ config = PoolInitializationConfig({
tokens: InputHelpers.sortTokens(tokens),
exactAmountsIn: exactAmountsIn,
minBptAmountOut: minBptAmountOut,
diff --git a/packages/foundry/script/DeployConstantSum.s.sol b/packages/foundry/script/DeployConstantSum.s.sol
index 686f2ed2..559d914f 100644
--- a/packages/foundry/script/DeployConstantSum.s.sol
+++ b/packages/foundry/script/DeployConstantSum.s.sol
@@ -10,7 +10,6 @@ import {
import { IRateProvider } from "@balancer-labs/v3-interfaces/contracts/vault/IRateProvider.sol";
import { InputHelpers } from "@balancer-labs/v3-solidity-utils/contracts/helpers/InputHelpers.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
-import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
import { PoolHelpers } from "./PoolHelpers.sol";
import { ScaffoldHelpers, console } from "./ScaffoldHelpers.sol";
@@ -21,18 +20,18 @@ import { ConstantSumFactory } from "../contracts/pools/ConstantSumFactory.sol";
* @notice Deploys, registers, and initializes a Constant Sum Pool
*/
contract DeployConstantSum is PoolHelpers, ScaffoldHelpers {
- function deployConstantSum(IERC20 token1, IERC20 token2) internal {
+ function run(IERC20 token1, IERC20 token2) external virtual {
// Set the deployment configurations
uint32 pauseWindowDuration = 365 days;
- RegistrationConfig memory regConfig = getRegistrationConfig(token1, token2);
- InitializationConfig memory initConfig = getInitializationConfig(token1, token2);
+ PoolRegistrationConfig memory regConfig = getPoolRegistrationConfig(token1, token2);
+ PoolInitializationConfig memory initConfig = getPoolInitializationConfig(token1, token2);
// Start creating the transactions
uint256 deployerPrivateKey = getDeployerPrivateKey();
vm.startBroadcast(deployerPrivateKey);
// Deploy a constant sum factory contract
- ConstantSumFactory factory = new ConstantSumFactory(IVault(vault), pauseWindowDuration);
+ ConstantSumFactory factory = new ConstantSumFactory(vault, pauseWindowDuration);
console.log("Constant Sum Factory deployed at: %s", address(factory));
// Deploy a pool and register it with the vault
@@ -49,8 +48,14 @@ contract DeployConstantSum is PoolHelpers, ScaffoldHelpers {
);
console.log("Constant Sum Pool deployed at: %s", pool);
+ // Approve Permit2 contract to spend tokens on behalf of deployer
+ approveSpenderOnToken(address(permit2), initConfig.tokens);
+
+ // Approve Router contract to spend tokens using Permit2
+ approveSpenderOnPermit2(address(router), initConfig.tokens);
+
// Seed the pool with initial liquidity
- initializePool(
+ router.initialize(
pool,
initConfig.tokens,
initConfig.exactAmountsIn,
@@ -68,10 +73,10 @@ contract DeployConstantSum is PoolHelpers, ScaffoldHelpers {
* For STANDARD tokens, the rate provider address must be 0, and paysYieldFees must be false.
* All WITH_RATE tokens need a rate provider, and may or may not be yield-bearing.
*/
- function getRegistrationConfig(
+ function getPoolRegistrationConfig(
IERC20 token1,
IERC20 token2
- ) internal view returns (RegistrationConfig memory regConfig) {
+ ) internal view returns (PoolRegistrationConfig memory config) {
string memory name = "Constant Sum Pool"; // name for the pool
string memory symbol = "CSP"; // symbol for the BPT
bytes32 salt = keccak256(abi.encode(block.number)); // salt for the pool deployment via factory
@@ -105,7 +110,7 @@ contract DeployConstantSum is PoolHelpers, ScaffoldHelpers {
enableDonation: false
});
- regConfig = RegistrationConfig({
+ config = PoolRegistrationConfig({
name: name,
symbol: symbol,
salt: salt,
@@ -122,10 +127,10 @@ contract DeployConstantSum is PoolHelpers, ScaffoldHelpers {
* @dev Set the pool initialization configurations here
* @notice this is where the amounts of tokens to be initially added to the pool are set
*/
- function getInitializationConfig(
+ function getPoolInitializationConfig(
IERC20 token1,
IERC20 token2
- ) internal pure returns (InitializationConfig memory poolInitConfig) {
+ ) internal pure returns (PoolInitializationConfig memory config) {
IERC20[] memory tokens = new IERC20[](2); // Array of tokens to be used in the pool
tokens[0] = token1;
tokens[1] = token2;
@@ -136,7 +141,7 @@ contract DeployConstantSum is PoolHelpers, ScaffoldHelpers {
bool wethIsEth = false; // If true, incoming ETH will be wrapped to WETH; otherwise the Vault will pull WETH tokens
bytes memory userData = bytes(""); // Additional (optional) data required for adding initial liquidity
- poolInitConfig = InitializationConfig({
+ config = PoolInitializationConfig({
tokens: InputHelpers.sortTokens(tokens),
exactAmountsIn: exactAmountsIn,
minBptAmountOut: minBptAmountOut,
diff --git a/packages/foundry/script/DeployMockTokens.s.sol b/packages/foundry/script/DeployMockTokens.s.sol
index 4e58bb76..dfebe5c8 100644
--- a/packages/foundry/script/DeployMockTokens.s.sol
+++ b/packages/foundry/script/DeployMockTokens.s.sol
@@ -14,7 +14,7 @@ import { MockVeBAL } from "../contracts/mocks/MockVeBAL.sol";
* @notice Deploys mock tokens for use with pools and hooks
*/
contract DeployMockTokens is ScaffoldHelpers {
- function deployMockTokens() internal returns (IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) {
+ function run() external virtual returns (IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) {
uint256 deployerPrivateKey = getDeployerPrivateKey();
vm.startBroadcast(deployerPrivateKey);
diff --git a/packages/foundry/script/PoolHelpers.sol b/packages/foundry/script/PoolHelpers.sol
index 51cf9d87..1e8e24d4 100644
--- a/packages/foundry/script/PoolHelpers.sol
+++ b/packages/foundry/script/PoolHelpers.sol
@@ -9,17 +9,15 @@ import {
import { IRouter } from "@balancer-labs/v3-interfaces/contracts/vault/IRouter.sol";
import { IPermit2 } from "permit2/src/interfaces/IPermit2.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
+import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
+import { IRouter } from "@balancer-labs/v3-interfaces/contracts/vault/IRouter.sol";
/**
- * A collection of addresses and helper functions for deploying pools
+ * @title Pool Helpers
+ * @notice Helpful types, interface instances, and functions for deploying pools on Balancer v3
*/
contract PoolHelpers {
- // BalancerV3 Sepolia addresses (5th testnet release)
- address internal vault = 0x92B5c1CB2999c45804A60d6529D77DeEF00fb839;
- address internal router = 0xa12Da7dfD0792a10a5b05B575545Bd685798Ce35;
- address internal permit2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
-
- struct RegistrationConfig {
+ struct PoolRegistrationConfig {
string name;
string symbol;
bytes32 salt;
@@ -31,7 +29,7 @@ contract PoolHelpers {
LiquidityManagement liquidityManagement;
}
- struct InitializationConfig {
+ struct PoolInitializationConfig {
IERC20[] tokens;
uint256[] exactAmountsIn;
uint256 minBptAmountOut;
@@ -39,24 +37,10 @@ contract PoolHelpers {
bytes userData;
}
- /**
- * @notice Approves the vault to spend tokens and then initializes the pool
- */
- function initializePool(
- address pool,
- IERC20[] memory tokens,
- uint256[] memory exactAmountsIn,
- uint256 minBptAmountOut,
- bool wethIsEth,
- bytes memory userData
- ) internal {
- // Approve Permit2 to spend account tokens
- approveSpenderOnToken(address(permit2), tokens);
- // Approve Router to spend account tokens using Permit2
- approveSpenderOnPermit2(address(router), tokens);
- // Initialize pool with the tokens that have been permitted
- IRouter(router).initialize(pool, tokens, exactAmountsIn, minBptAmountOut, wethIsEth, userData);
- }
+ // BalancerV3 Sepolia addresses (6th testnet release)
+ IVault internal vault = IVault(0x92B5c1CB2999c45804A60d6529D77DeEF00fb839);
+ IRouter internal router = IRouter(0xa12Da7dfD0792a10a5b05B575545Bd685798Ce35);
+ IPermit2 internal permit2 = IPermit2(0x000000000022D473030F116dDEE9F6B43aC78BA3);
/**
* Sorts the tokenConfig array into alphanumeric order
@@ -94,7 +78,7 @@ contract PoolHelpers {
uint160 maxAmount = type(uint160).max;
uint48 maxExpiration = type(uint48).max;
for (uint256 i = 0; i < tokens.length; ++i) {
- IPermit2(permit2).approve(address(tokens[i]), spender, maxAmount, maxExpiration);
+ permit2.approve(address(tokens[i]), spender, maxAmount, maxExpiration);
}
}
}
diff --git a/packages/foundry/test/VeBALFeeDiscountHook.t.sol b/packages/foundry/test/VeBALFeeDiscountHook.t.sol
index bbdce7a7..24bc21c6 100644
--- a/packages/foundry/test/VeBALFeeDiscountHook.t.sol
+++ b/packages/foundry/test/VeBALFeeDiscountHook.t.sol
@@ -23,6 +23,7 @@ import { PoolFactoryMock } from "@balancer-labs/v3-vault/contracts/test/PoolFact
import { RouterMock } from "@balancer-labs/v3-vault/contracts/test/RouterMock.sol";
import { VeBALFeeDiscountHook } from "../contracts/hooks/VeBALFeeDiscountHook.sol";
+import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract VeBALFeeDiscountHookTest is BaseVaultTest {
using FixedPoint for uint256;
@@ -48,7 +49,7 @@ contract VeBALFeeDiscountHookTest is BaseVaultTest {
// lp will be the owner of the hook. Only LP is able to set hook fee percentages.
vm.prank(lp);
address veBalFeeHook = address(
- new VeBALFeeDiscountHook(IVault(address(vault)), address(factoryMock), address(veBAL), trustedRouter)
+ new VeBALFeeDiscountHook(IVault(address(vault)), address(factoryMock), trustedRouter, IERC20(veBAL))
);
vm.label(veBalFeeHook, "VeBAL Fee Hook");
return veBalFeeHook;
diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts
index c513effa..8e0ef77f 100644
--- a/packages/nextjs/contracts/deployedContracts.ts
+++ b/packages/nextjs/contracts/deployedContracts.ts
@@ -1865,14 +1865,14 @@ const deployedContracts = {
internalType: "address",
},
{
- name: "veBAL",
+ name: "trustedRouter",
type: "address",
internalType: "address",
},
{
- name: "trustedRouter",
+ name: "veBAL",
type: "address",
- internalType: "address",
+ internalType: "contract IERC20",
},
],
stateMutability: "nonpayable",
@@ -2417,12 +2417,12 @@ const deployedContracts = {
],
outputs: [
{
- name: "",
+ name: "success",
type: "bool",
internalType: "bool",
},
{
- name: "",
+ name: "dynamicSwapFee",
type: "uint256",
internalType: "uint256",
},
@@ -2519,19 +2519,7 @@ const deployedContracts = {
],
},
],
- inheritedFunctions: {
- getHookFlags: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onAfterAddLiquidity: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onAfterInitialize: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onAfterRemoveLiquidity: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onAfterSwap: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onBeforeAddLiquidity: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onBeforeInitialize: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onBeforeRemoveLiquidity: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onBeforeSwap: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onComputeDynamicSwapFee: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- onRegister: "lib/balancer-v3-monorepo/pkg/vault/contracts/BaseHooks.sol",
- },
+ inheritedFunctions: {},
},
},
} as const;
From a6f15ed494db3cb080be98794efe93704cc195dd Mon Sep 17 00:00:00 2001
From: Matthew Pereira
Date: Wed, 14 Aug 2024 16:49:25 -0700
Subject: [PATCH 5/7] Update hooks page design
---
.../app/hooks/_components/HooksCards.tsx | 38 +++++++++----------
packages/nextjs/app/hooks/page.tsx | 10 ++++-
.../nextjs/contracts/deployedContracts.ts | 12 +++---
3 files changed, 34 insertions(+), 26 deletions(-)
diff --git a/packages/nextjs/app/hooks/_components/HooksCards.tsx b/packages/nextjs/app/hooks/_components/HooksCards.tsx
index 6ddcfda2..55920dd3 100644
--- a/packages/nextjs/app/hooks/_components/HooksCards.tsx
+++ b/packages/nextjs/app/hooks/_components/HooksCards.tsx
@@ -36,26 +36,26 @@ export const HooksCards = ({ hooks }: { hooks: HookDetails[] }) => {
return (
<>
-
- {hooks.map(hook => (
-
setActiveModal(hook.id)}
+ {hooks.map(hook => (
+
setActiveModal(hook.id)}
+ >
+
{hook.title}
+
-
-
-
{hook.title}
-
-
-
-
- {/*
Created By {hook.created_by}
*/}
-
-
{hook.description}
-
- ))}
-
+
+ {hook.github.slice(0, 40)}...
+
+
{hook.category}
+
{hook.created_by}
+
+ ))}
{activeModal && (
setActiveModal(null)}>
diff --git a/packages/nextjs/app/hooks/page.tsx b/packages/nextjs/app/hooks/page.tsx
index c2147832..20b76b11 100644
--- a/packages/nextjs/app/hooks/page.tsx
+++ b/packages/nextjs/app/hooks/page.tsx
@@ -39,7 +39,15 @@ const Hooks: NextPage = async () => {
.
- {hooks ? : Error fetching hooks data!
}
+
+
+
Name
+
Repo URL
+
Category
+
Created By
+
+ {hooks ?
:
Error fetching hooks data!
}
+
);
};
diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts
index 8e0ef77f..2cec3129 100644
--- a/packages/nextjs/contracts/deployedContracts.ts
+++ b/packages/nextjs/contracts/deployedContracts.ts
@@ -7,7 +7,7 @@ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";
const deployedContracts = {
31337: {
MockToken1: {
- address: "0x8e8cB505973E04200554Bd98741086C7Eca9f42a",
+ address: "0x290F385a98e707275366648817403E415a808a63",
abi: [
{
type: "constructor",
@@ -365,7 +365,7 @@ const deployedContracts = {
},
},
MockToken2: {
- address: "0xC2D1A7c03C0459a8d0Ee885283CE828DE5fFf617",
+ address: "0x3D10F2021266d0d83090046fDF0b8790779C2A82",
abi: [
{
type: "constructor",
@@ -723,7 +723,7 @@ const deployedContracts = {
},
},
MockVeBAL: {
- address: "0x906e3a6d1baf80e3e3fa3D57A5DA73099Da86C4c",
+ address: "0xd213c4cC9Bd38bc7dC8877e5f53955c3E5F5F416",
abi: [
{
type: "constructor",
@@ -1081,7 +1081,7 @@ const deployedContracts = {
},
},
ConstantSumFactory: {
- address: "0x68c87F9fB214Bb4856a13c9123f9b0624944D1A6",
+ address: "0x90e1d376163cb8287ae4fF1f15CbD4F594DF6201",
abi: [
{
type: "constructor",
@@ -1465,7 +1465,7 @@ const deployedContracts = {
},
},
ConstantProductFactory: {
- address: "0x2a374E85Ca5F1af906De5CdDa3658219e8759097",
+ address: "0x98Ae3884f844035F02d1eEbE94E54C25bCb53794",
abi: [
{
type: "constructor",
@@ -1849,7 +1849,7 @@ const deployedContracts = {
},
},
VeBALFeeDiscountHook: {
- address: "0xb33ca895101aB93835fd846d8C23FBdBC29d5843",
+ address: "0x7798AD4e898a948FFCf426fb2aAdffbD01087085",
abi: [
{
type: "constructor",
From aa868a9229aba75d2bb6fc58e8784220deb70c0b Mon Sep 17 00:00:00 2001
From: Matthew Pereira
Date: Thu, 15 Aug 2024 08:37:16 -0700
Subject: [PATCH 6/7] Rename deploy scripts for clarity
---
...kTokens.s.sol => 00_DeployMockTokens.s.sol} | 0
...antSum.s.sol => 01_DeployConstantSum.s.sol} | 0
...ct.s.sol => 02_DeployConstantProduct.s.sol} | 0
packages/foundry/script/Deploy.s.sol | 18 ++++++++----------
4 files changed, 8 insertions(+), 10 deletions(-)
rename packages/foundry/script/{DeployMockTokens.s.sol => 00_DeployMockTokens.s.sol} (100%)
rename packages/foundry/script/{DeployConstantSum.s.sol => 01_DeployConstantSum.s.sol} (100%)
rename packages/foundry/script/{DeployConstantProduct.s.sol => 02_DeployConstantProduct.s.sol} (100%)
diff --git a/packages/foundry/script/DeployMockTokens.s.sol b/packages/foundry/script/00_DeployMockTokens.s.sol
similarity index 100%
rename from packages/foundry/script/DeployMockTokens.s.sol
rename to packages/foundry/script/00_DeployMockTokens.s.sol
diff --git a/packages/foundry/script/DeployConstantSum.s.sol b/packages/foundry/script/01_DeployConstantSum.s.sol
similarity index 100%
rename from packages/foundry/script/DeployConstantSum.s.sol
rename to packages/foundry/script/01_DeployConstantSum.s.sol
diff --git a/packages/foundry/script/DeployConstantProduct.s.sol b/packages/foundry/script/02_DeployConstantProduct.s.sol
similarity index 100%
rename from packages/foundry/script/DeployConstantProduct.s.sol
rename to packages/foundry/script/02_DeployConstantProduct.s.sol
diff --git a/packages/foundry/script/Deploy.s.sol b/packages/foundry/script/Deploy.s.sol
index 1f7d1433..c66434ce 100644
--- a/packages/foundry/script/Deploy.s.sol
+++ b/packages/foundry/script/Deploy.s.sol
@@ -2,18 +2,18 @@
pragma solidity ^0.8.24;
import { ScaffoldHelpers } from "./ScaffoldHelpers.sol";
-import { DeployMockTokens } from "./DeployMockTokens.s.sol";
-import { DeployConstantSum } from "./DeployConstantSum.s.sol";
-import { DeployConstantProduct } from "./DeployConstantProduct.s.sol";
+import { DeployMockTokens } from "./00_DeployMockTokens.s.sol";
+import { DeployConstantSum } from "./01_DeployConstantSum.s.sol";
+import { DeployConstantProduct } from "./02_DeployConstantProduct.s.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
/**
* @title Deploy Script
- * @notice Import all deploy scripts here so that scaffold can exportDeployments()
+ * @dev Import & run deploy scripts here so that contract Abis are carried to /nextjs
* @dev Run this script with `yarn deploy`
*/
contract DeployScript is ScaffoldHelpers {
- function run() external virtual {
+ function run() external virtual export {
// Deploy mock tokens to be used for pools and hooks contracts
DeployMockTokens deployMockTokens = new DeployMockTokens();
(IERC20 mockToken1, IERC20 mockToken2, IERC20 mockVeBAL) = deployMockTokens.run();
@@ -25,12 +25,10 @@ contract DeployScript is ScaffoldHelpers {
// Deploy a constant product factory, a hooks contract, and a pool
DeployConstantProduct deployConstantProduct = new DeployConstantProduct();
deployConstantProduct.run(mockToken1, mockToken2, mockVeBAL);
+ }
- /**
- * This function generates the file containing the contracts Abi definitions that are carried from /foundry to /nextjs.
- * These definitions are used to derive the types needed in the custom scaffold-eth hooks, for example.
- * This function should be called last.
- */
+ modifier export() {
+ _;
exportDeployments();
}
}
From 4df059d13384284a4f401c8077f8f6d547167390 Mon Sep 17 00:00:00 2001
From: Matthew Pereira
Date: Thu, 15 Aug 2024 09:28:02 -0700
Subject: [PATCH 7/7] Update README with deploy script changes
---
README.md | 82 ++++++++++++++++++++++++-------------------------------
1 file changed, 35 insertions(+), 47 deletions(-)
diff --git a/README.md b/README.md
index 84d02c85..849b02e9 100644
--- a/README.md
+++ b/README.md
@@ -15,16 +15,17 @@ A full stack prototyping tool for building on top of Balancer v3. Accelerate the
### ๐ชง Table Of Contents
-0. [Environment Setup ๐งโ๐ป](#0-environment-setup-)
-1. [Create a Custom Pool ๐](#1-create-a-custom-pool-)
-2. [Create a Pool Factory ๐ญ](#2-create-a-pool-factory-)
-3. [Create a Pool Hook ๐ช](#3-create-a-pool-hook-)
-4. [Deploy the Contracts ๐ข](#4-deploy-the-contracts-)
-5. [Test the Contracts ๐งช](#5-test-the-contracts-)
+- [๐งโ๐ป Environment Setup](#0-environment-setup-)
+- [๐ Create a Custom Pool](#1-create-a-custom-pool-)
+- [๐ญ Create a Pool Factory](#2-create-a-pool-factory-)
+- [๐ช Create a Pool Hook](#3-create-a-pool-hook-)
+- [๐ข Deploy the Contracts](#4-deploy-the-contracts-)
+- [๐งช Test the Contracts](#5-test-the-contracts-)
-## 0. Environment Setup ๐งโ๐ป
+## ๐งโ๐ป Environment Setup
-[![image](https://github.com/user-attachments/assets/2d0d5c6d-647d-4782-8d7a-9076b39319b9)](https://www.youtube.com/watch?v=2lInvpCt2o4)
+
+
### ๐ Requirements
@@ -144,7 +145,7 @@ const scaffoldConfig = {
-## 1. Create a Custom Pool ๐
+## ๐ 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.
@@ -162,7 +163,7 @@ Your journey begins with planning the custom computation logic for the pool, whi
- To get started, edit the`ConstantSumPool.sol` contract directly or make a copy
-## 2. Create a Pool Factory ๐ญ
+## ๐ญ 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
@@ -180,7 +181,7 @@ After designing a pool contract, the next step is to prepare a factory contract
- To get started, edit the`ConstantSumFactory.sol` contract directly or make a copy
-## 3. Create a Pool Hook ๐ช
+## ๐ช 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
@@ -198,33 +199,39 @@ Next, consider further extending the functionality of the custom pool contract w
- To get started, edit the `VeBALFeeDiscountHook.sol` contract directly or make a copy
-## 4. Deploy the Contracts ๐ข
+## ๐ข Deploy the Contracts
-The deploy scripts are all located in the [foundry/script/](https://github.com/balancer/scaffold-balancer-v3/tree/main/packages/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](http://localhost:3000/pools) page will automatically add a button above the search bar for any pools deployed using the latest factory contract
+The deploy scripts are all located in the [foundry/script/](https://github.com/balancer/scaffold-balancer-v3/tree/main/packages/foundry/script) directory. All deploy scripts should be run inside of `Deploy.s.sol` so that the `export` modifier can automate the transfer of deployed contract info to `nextjs/contracts/depoloyedContracts.ts`
-### ๐ ๏ธ Adjust the Deploy Scripts
+### ๐ฏ Follow the Pattern
-#### `00_DeploySetup.s.sol`
+To add a new deploy script, import it into `Deploy.s.sol`, create a new instance of it, and run it
-Deploy mock tokens, factory contracts, and hooks contracts to be used by pools
+```
+function run() external virtual export {
+ DeployYourContract deployYourContract = new DeployYourContract();
+ deployYourContract.run();
+}
+```
-- Set the `pauseWindowDuration` for the factory contracts
-- Set the mock token names, symbols, and supply
-- Set any hooks contracts constructor args
+### ๐ ๏ธ Examine the Example Deploy Scripts
-#### `01_DeployConstantSumPool.s.sol`
+#### `00_DeployMockTokens.s.sol`
-Deploy, register, and initialize a Constant Sum Pool
+1. Deploys mock tokens that are used to register and initialize pools
+2. Deploys a mock token used for the example `VeBALFeeDiscountHook` contract
-- Set the pool registration config in the `getRegistrationConfig()` function
-- Set the pool initialization config in the `getInitializationConfig()` function
+#### `01_DeployConstantSum.s.sol`
-#### `02_DeployConstantProductPool.s.sol`
+1. Deploys a `ConstantSumFactory`
+2. Deploys and registers a `ConstantSumPool`
+3. Initializes the `ConstantSumPool` using mock tokens
-Deploy, register, and initialize a Constant Product Pool
+#### `02_DeployConstantProduct.s.sol`
-- Set the pool registration config in the `getRegistrationConfig()` function
-- Set the pool initialization config in the `getInitializationConfig()` function
+1. Deploys a `ConstantProductFactory`
+2. Deploys and registers a `ConstantProductPool`
+3. Initializes the `ConstantProductPool` using mock tokens
### ๐ก Broadcast the Transactions
@@ -234,28 +241,9 @@ To run all the deploy scripts
yarn deploy
```
-To run only the `DeploySetup` script
-
-```bash
-yarn deploy:setup
-```
-
-To run only the `DeployConstantSumPool` script
-
-```bash
-yarn deploy:sum
-```
-
-To run only the `DeployConstantProductPool` script
-
-```bash
-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](https://github.com/balancer/scaffold-balancer-v3/blob/main/packages/foundry/package.json)
-## 5. Test the Contracts ๐งช
+## ๐งช Test the Contracts
The [balancer-v3-monorepo](https://github.com/balancer/balancer-v3-monorepo) provides testing utility contracts like [BaseVaultTest](https://github.com/balancer/balancer-v3-monorepo/blob/main/pkg/vault/test/foundry/utils/BaseVaultTest.sol). Therefore, the best way to begin writing tests for custom factory, pool, and hook contracts is to utilize the patterns and methods established by the source code.