diff --git a/.gitmodules b/.gitmodules index 1822899..453fa74 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "lib/permit2"] path = lib/permit2 url = https://github.com/Uniswap/permit2 +[submodule "lib/reclamm"] + path = lib/reclamm + url = https://github.com/balancer/reclamm diff --git a/foundry.toml b/foundry.toml index 25b918f..3175d1b 100644 --- a/foundry.toml +++ b/foundry.toml @@ -3,4 +3,9 @@ src = "src" out = "out" libs = ["lib"] +evm_version = "cancun" + # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options + +[etherscan] +sonic = { key = "${ETHERSCAN_API_KEY}", chain = 146, url = "https://api.sonicscan.org/api"} \ No newline at end of file diff --git a/lib/balancer-v3-monorepo b/lib/balancer-v3-monorepo index 68cc540..6bf35d1 160000 --- a/lib/balancer-v3-monorepo +++ b/lib/balancer-v3-monorepo @@ -1 +1 @@ -Subproject commit 68cc540d16270044fc4ac6fbdcb24c2cf4fc87bf +Subproject commit 6bf35d1d6be50551a1dd3d355dfd384d8501101c diff --git a/lib/reclamm b/lib/reclamm new file mode 160000 index 0000000..8207b33 --- /dev/null +++ b/lib/reclamm @@ -0,0 +1 @@ +Subproject commit 8207b33c1ab76de3c42b015bab5210a8436376de diff --git a/remappings.txt b/remappings.txt index b2c4790..81c422c 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,4 +1,5 @@ @balancer-v3-monorepo/interfaces/=lib/balancer-v3-monorepo/pkg/interfaces/contracts/ @balancer-v3-monorepo/vault/=lib/balancer-v3-monorepo/pkg/vault/contracts/ @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ -@permit2/=lib/permit2/src/ \ No newline at end of file +@permit2/=lib/permit2/src/ +@reclamm/=lib/reclamm/contracts/ \ No newline at end of file diff --git a/script/ReClammPoolCreate.s.sol b/script/ReClammPoolCreate.s.sol new file mode 100644 index 0000000..e93b0a4 --- /dev/null +++ b/script/ReClammPoolCreate.s.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {IBufferRouter} from "@balancer-v3-monorepo/interfaces/vault/IBufferRouter.sol"; +import {TokenConfig, PoolRoleAccounts, TokenType} from "@balancer-v3-monorepo/interfaces/vault/VaultTypes.sol"; +import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {IPermit2} from "@permit2/interfaces/IPermit2.sol"; +import {IRateProvider} from "@balancer-v3-monorepo/interfaces/solidity-utils/helpers/IRateProvider.sol"; +/** + * To run against a local fork, start anvil: + * `$ anvil --fork-url RPC_URL + * Run script (in simulation mode): + * `$ forge script script/StableSurgeCreate.s.sol:StableSurgeCreate --fork-url http://localhost:8545 + */ + +interface IReClammPoolFactory { + function create( + string memory name, + string memory symbol, + TokenConfig[] memory tokens, + PoolRoleAccounts memory roleAccounts, + uint256 swapFeePercentage, + uint256 initialMinPrice, + uint256 initialMaxPrice, + uint256 initialTargetPrice, + uint256 priceShiftDailyRate, + uint64 centerednessMargin, + bytes32 salt + ) external returns (address pool); + function getPoolCount() external view returns (uint256); +} + +contract ReClammPoolCreate is Script { + IReClammPoolFactory poolFactory = IReClammPoolFactory(0x0f08eEf2C785AA5e7539684aF04755dEC1347b7c); + + IERC20 weth = IERC20(0x4200000000000000000000000000000000000006); + IERC20 usdc = IERC20(0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913); + + function run() public returns (uint256) { + // Add .env in root with PRIVATE_KEY + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + vm.startBroadcast(deployerPrivateKey); + + console.logUint(poolFactory.getPoolCount()); + + PoolRoleAccounts memory roleAccounts; + // beets deployer address, change to your own address, or remove completely to delegate to bal dao + roleAccounts.pauseManager = 0xb5e6b895734409Df411a052195eb4EE7e40d8696; + roleAccounts.swapFeeManager = 0xb5e6b895734409Df411a052195eb4EE7e40d8696; + + TokenConfig memory t1; + t1.token = weth; + t1.tokenType = TokenType.STANDARD; + TokenConfig memory t2; + + t2.token = usdc; + t2.tokenType = TokenType.STANDARD; + TokenConfig[] memory tokenConfigs = new TokenConfig[](2); + tokenConfigs[0] = t1; + tokenConfigs[1] = t2; + + address newPool = poolFactory.create( + "ReClamm weth/usdc", // Name + "RECLAMM-WETH-USDC", // Symbol + tokenConfigs, // tokens + roleAccounts, // roleAccounts + 0.001e18, // 0.1% swapFeePercentage + 1500e18, // 1500 initialMinPrice + 1800e18, // 1800 initialMaxPrice + 1650e18, // 1650 initialTargetPrice + 1e18, // 100% priceShiftDailyRate + 0.2e18, // 20% centerednessMargin + bytes32("salt1") + ); + + console.log(newPool); + + console.logUint(poolFactory.getPoolCount()); + + vm.stopBroadcast(); + + return 0; + } +} diff --git a/script/ReClammPoolInitialize.s.sol b/script/ReClammPoolInitialize.s.sol new file mode 100644 index 0000000..496f26f --- /dev/null +++ b/script/ReClammPoolInitialize.s.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.22; + +import "forge-std/Script.sol"; +import {IRouter} from "@balancer-v3-monorepo/interfaces/vault/IRouter.sol"; +import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {IPermit2} from "@permit2/interfaces/IPermit2.sol"; +import {IVault} from "@balancer-v3-monorepo/interfaces/vault/IVault.sol"; +import {IReClammPool} from "@reclamm/interfaces/IReClammPool.sol"; + +contract ReClammPoolInitialize is Script { + IPermit2 public constant permit2 = IPermit2(0x000000000022D473030F116dDEE9F6B43aC78BA3); + IRouter public constant router = IRouter(0x3f170631ed9821Ca51A59D996aB095162438DC10); + IVault public constant vault = IVault(0xbA1333333333a1BA1108E8412f11850A5C319bA9); + IReClammPool public constant pool = IReClammPool(0xde842Def79C17A52D7FB4b61c238D78fD18F11e6); + IERC20 weth = IERC20(0x4200000000000000000000000000000000000006); + IERC20 usdc = IERC20(0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913); + + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + uint256 initialBalanceRatio = pool.computeInitialBalanceRatio(); + console.log("initialBalanceRatio", initialBalanceRatio); + + uint256 wethAmount = 0.00025e18; + uint256 usdcAmount = wethAmount * initialBalanceRatio / 1e18 / 1e12; + + console.log("usdcAmount", usdcAmount); + console.log("wethAmount", wethAmount); + + IERC20[] memory tokens = new IERC20[](2); + tokens[0] = weth; + tokens[1] = usdc; + + uint256[] memory exactAmountsIn = new uint256[](2); + exactAmountsIn[0] = wethAmount; + exactAmountsIn[1] = usdcAmount; + + uint256 minBptAmountOut = 0; + bool wethIsEth = false; + bytes memory userData = ""; + + usdc.approve(address(permit2), 100_000_000e18); + permit2.approve(address(usdc), address(router), type(uint160).max, type(uint48).max); + + weth.approve(address(permit2), 100_000_000e18); + permit2.approve(address(weth), address(router), type(uint160).max, type(uint48).max); + + router.initialize(address(pool), tokens, exactAmountsIn, minBptAmountOut, wethIsEth, userData); + vm.stopBroadcast(); + } +}