diff --git a/packages/foundry/script/DeployFactoryAndPool.s.sol b/packages/foundry/script/DeployFactoryAndPool.s.sol index dc7e6aba..2ea37925 100644 --- a/packages/foundry/script/DeployFactoryAndPool.s.sol +++ b/packages/foundry/script/DeployFactoryAndPool.s.sol @@ -7,6 +7,8 @@ import "./ScaffoldETHDeploy.s.sol"; import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; import {TokenConfig} from "@balancer-labs/v3-interfaces/contracts/vault/VaultTypes.sol"; import {HelperConfig} from "../utils/HelperConfig.sol"; +import {ArrayHelpers} from "@balancer-labs/v3-solidity-utils/contracts/helpers/ArrayHelpers.sol"; +import {InputHelpers} from "@balancer-labs/v3-solidity-utils/contracts/helpers/InputHelpers.sol"; /** * @title DeployFactoryAndPool @@ -28,7 +30,7 @@ contract DeployFactoryAndPool is ScaffoldETHDeploy, DeployPool { // Deploy mock tokens. Remove this if using already deployed tokens and instead set the tokens above vm.startBroadcast(deployerPrivateKey); - (IERC20 token1, IERC20 token2) = deployMockTokens(); + (address mockToken1, address mockToken2) = deployMockTokens(); vm.stopBroadcast(); // Look up configuration options from `HelperConfig.sol` @@ -38,7 +40,7 @@ contract DeployFactoryAndPool is ScaffoldETHDeploy, DeployPool { string memory name, string memory symbol, TokenConfig[] memory tokenConfig - ) = helperConfig.getPoolConfig(token1, token2); + ) = helperConfig.getPoolConfig(mockToken1, mockToken2); ( IERC20[] memory tokens, uint256[] memory exactAmountsIn, @@ -58,8 +60,10 @@ contract DeployFactoryAndPool is ScaffoldETHDeploy, DeployPool { address(customPoolFactory), name, symbol, - tokenConfig + helperConfig.sortTokenConfig(tokenConfig) ); + + tokens = InputHelpers.sortTokens(tokens); initializePool( pool, tokens, diff --git a/packages/foundry/script/DeployPool.s.sol b/packages/foundry/script/DeployPool.s.sol index f5c9262d..09e0be29 100644 --- a/packages/foundry/script/DeployPool.s.sol +++ b/packages/foundry/script/DeployPool.s.sol @@ -9,6 +9,8 @@ import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; import {TokenConfig} from "@balancer-labs/v3-interfaces/contracts/vault/VaultTypes.sol"; import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; import {Script, console} from "forge-std/Script.sol"; +import {InputHelpers} from "@balancer-labs/v3-solidity-utils/contracts/helpers/InputHelpers.sol"; +import {HelperConfig} from "../utils/HelperConfig.sol"; /** * @title DeployPool Script @@ -18,6 +20,8 @@ import {Script, console} from "forge-std/Script.sol"; */ contract DeployPool is HelperFunctions, HelperConfig, Script { error InvalidPrivateKey(string); + string name = "Scaffold Balancer Constant Price Pool #2"; // name for the pool + string symbol = "POOL2-SB-50scUSD-50scDAI"; // symbol for the BPT /** * @dev Set your pool deployment and initialization configurations in `HelperConfig.sol` @@ -31,18 +35,21 @@ contract DeployPool is HelperFunctions, HelperConfig, Script { ); } - // Deploy mock tokens to use in the pool - vm.startBroadcast(deployerPrivateKey); - (IERC20 token1, IERC20 token2) = deployMockTokens(); - vm.stopBroadcast(); + address mockToken1 = DevOpsTools.get_most_recent_deployment( + "MockToken1", // Must match the mock token contract name + block.chainid + ); + address mockToken2 = DevOpsTools.get_most_recent_deployment( + "MockToken2", // Must match the mock token contract name + block.chainid + ); // Look up configurations from `HelperConfig.sol` HelperConfig helperConfig = new HelperConfig(); - ( - string memory name, - string memory symbol, - TokenConfig[] memory tokenConfig - ) = helperConfig.getPoolConfig(token1, token2); + (, , TokenConfig[] memory tokenConfig) = helperConfig.getPoolConfig( + mockToken1, + mockToken2 + ); ( IERC20[] memory tokens, uint256[] memory exactAmountsIn, @@ -61,8 +68,9 @@ contract DeployPool is HelperFunctions, HelperConfig, Script { poolFactoryAddress, name, symbol, - tokenConfig + helperConfig.sortTokenConfig(tokenConfig) ); + tokens = InputHelpers.sortTokens(tokens); initializePool( pool, tokens, diff --git a/packages/foundry/utils/HelperConfig.sol b/packages/foundry/utils/HelperConfig.sol index 48f233c9..6cddb711 100644 --- a/packages/foundry/utils/HelperConfig.sol +++ b/packages/foundry/utils/HelperConfig.sol @@ -20,22 +20,14 @@ contract HelperConfig { IVault public vault = IVault(0x1FC7F1F84CFE61a04224AC8D3F87f56214FeC08c); IRouter public router = IRouter(0xA0De078cd5cFa7088821B83e0bD7545ccfb7c883); - /** - * @dev Tokens for pool (also requires configuration of `TokenConfig` in the `getPoolConfig` function) - * @dev If using already deployed tokens, set the addresses here and remove the args for `getPoolConfig` function - * @notice the args for `getPoolConfig` enable the use of mock tokens that are not yet deployed - */ - IERC20 mockToken1; // Make sure to have proper token order (alphanumeric) - IERC20 mockToken2; // Make sure to have proper token order (alphanumeric) - /** * @notice Creates mock tokens for the pool and mints 1000 of each to the deployer wallet */ - function deployMockTokens() internal returns (IERC20, IERC20) { + function deployMockTokens() internal returns (address, address) { MockToken1 scUSD = new MockToken1("Scaffold USD", "scUSD"); MockToken2 scDAI = new MockToken2("Scaffold DAI", "scDAI"); - return (scDAI, scUSD); + return (address(scDAI), address(scUSD)); } /** @@ -53,8 +45,8 @@ contract HelperConfig { * @dev Set the name, symbol, and token configuration for the pool here */ function getPoolConfig( - IERC20 token1, - IERC20 token2 + address token1, + address token2 ) public pure @@ -69,13 +61,13 @@ contract HelperConfig { 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, + token: IERC20(token1), tokenType: TokenType.STANDARD, // STANDARD, WITH_RATE, or ERC4626 rateProvider: IRateProvider(address(0)), // The rate provider for a token yieldFeeExempt: false // Flag indicating whether yield fees should be charged on this token }); tokenConfig[1] = TokenConfig({ // Make sure to have proper token order (alphanumeric) - token: token2, + token: IERC20(token2), tokenType: TokenType.STANDARD, // STANDARD, WITH_RATE, or ERC4626 rateProvider: IRateProvider(address(0)), // The rate provider for a token yieldFeeExempt: false // Flag indicating whether yield fees should be charged on this token @@ -108,4 +100,22 @@ contract HelperConfig { wethIsEth = false; // If true, incoming ETH will be wrapped to WETH; otherwise the Vault will pull WETH tokens userData = bytes(""); // Additional (optional) data required for adding initial liquidity } + + function sortTokenConfig( + TokenConfig[] memory tokenConfig + ) public pure returns (TokenConfig[] memory) { + for (uint256 i = 0; i < tokenConfig.length - 1; i++) { + for (uint256 j = 0; j < tokenConfig.length - i - 1; j++) { + if (tokenConfig[j].token > tokenConfig[j + 1].token) { + // Swap if they're out of order. + (tokenConfig[j], tokenConfig[j + 1]) = ( + tokenConfig[j + 1], + tokenConfig[j] + ); + } + } + } + + return tokenConfig; + } }