diff --git a/bolt-contracts/config/holesky/vaults.json b/bolt-contracts/config/holesky/vaults.json new file mode 100644 index 000000000..3e56143b1 --- /dev/null +++ b/bolt-contracts/config/holesky/vaults.json @@ -0,0 +1,10 @@ +[ + { + "collateral": "0x8d09a4502Cc8Cf1547aD300E066060D043f6982D", + "admin": "0x20A1305Ec6c13FFE8e5289f98ba1A18Aa262c15E" + }, + { + "collateral": "0x7322c24752f79c05FFD1E2a6FCB97020C1C264F1", + "admin": "0x20A1305Ec6c13FFE8e5289f98ba1A18Aa262c15E" + } +] \ No newline at end of file diff --git a/bolt-contracts/script/holesky/admin/helpers/DeployVaults.s.sol b/bolt-contracts/script/holesky/admin/helpers/DeployVaults.s.sol new file mode 100644 index 000000000..820fb3c34 --- /dev/null +++ b/bolt-contracts/script/holesky/admin/helpers/DeployVaults.s.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import {Script, console} from "forge-std/Script.sol"; + +import {INetworkRegistry} from "@symbiotic/interfaces/INetworkRegistry.sol"; +import {IOperatorRegistry} from "@symbiotic/interfaces/IOperatorRegistry.sol"; +import {IVaultFactory} from "@symbiotic/interfaces/IVaultFactory.sol"; +import {IVault} from "@symbiotic/interfaces/vault/IVault.sol"; +import {IOptInService} from "@symbiotic/interfaces/service/IOptInService.sol"; +import {IVaultConfigurator} from "@symbiotic/interfaces/IVaultConfigurator.sol"; +import {IBaseDelegator} from "@symbiotic/interfaces/delegator/IBaseDelegator.sol"; +import {IBaseSlasher} from "@symbiotic/interfaces/slasher/IBaseSlasher.sol"; +import {IMetadataService} from "@symbiotic/interfaces/service/IMetadataService.sol"; +import {INetworkRestakeDelegator} from "@symbiotic/interfaces/delegator/INetworkRestakeDelegator.sol"; +import {INetworkMiddlewareService} from "@symbiotic/interfaces/service/INetworkMiddlewareService.sol"; +import {ISlasherFactory} from "@symbiotic/interfaces/ISlasherFactory.sol"; +import {IVetoSlasher} from "@symbiotic/interfaces/slasher/IVetoSlasher.sol"; +import {IDelegatorFactory} from "@symbiotic/interfaces/IDelegatorFactory.sol"; +import {IMigratablesFactory} from "@symbiotic/interfaces/common/IMigratablesFactory.sol"; +import {Subnetwork} from "@symbiotic/contracts/libraries/Subnetwork.sol"; + +contract DeploySymbioticVaults is Script { + struct VaultConfig { + address admin; + address collateral; + } + + function run() public { + IVaultConfigurator vaultConfigurator = _readVaultConfigurator(); + VaultConfig[] memory configs = _readVaultConfigs(); + uint48 epochDuration = _readEpochDuration(); + + // TODO: Check if vaults for specific collateral are already deployed + + vm.startBroadcast(); + + for (uint256 i; i < configs.length; ++i) { + VaultConfig memory config = configs[i]; + + console.log("Deploying vault with collateral:", config.collateral); + + address[] memory adminRoleHolders = new address[](1); + adminRoleHolders[0] = config.admin; + + IVaultConfigurator.InitParams memory vaultConfiguratorInitParams = IVaultConfigurator.InitParams({ + version: IMigratablesFactory(vaultConfigurator.VAULT_FACTORY()).lastVersion(), + owner: config.admin, + vaultParams: abi.encode( + IVault.InitParams({ + collateral: config.collateral, + burner: address(0xdead), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: config.admin, + depositWhitelistSetRoleHolder: config.admin, + depositorWhitelistRoleHolder: config.admin, + isDepositLimitSetRoleHolder: config.admin, + depositLimitSetRoleHolder: config.admin + }) + ), + delegatorIndex: 0, // Use NetworkRestakeDelegator + delegatorParams: abi.encode( + INetworkRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: config.admin, + hook: address(0), // we don't need a hook + hookSetRoleHolder: config.admin + }), + networkLimitSetRoleHolders: adminRoleHolders, + operatorNetworkSharesSetRoleHolders: adminRoleHolders + }) + ), + withSlasher: true, + slasherIndex: 1, // Use VetoSlasher + slasherParams: abi.encode( + IVetoSlasher.InitParams({ + baseParams: IBaseSlasher.BaseParams({ + isBurnerHook: false // ? + }), + // veto duration must be smaller than epoch duration + vetoDuration: uint48(12 hours), + resolverSetEpochsDelay: 3 + }) + ) + }); + + (address vault, address networkRestakeDelegator, address vetoSlasher) = + vaultConfigurator.create(vaultConfiguratorInitParams); + + console.log("Deployed vault with collateral:", config.collateral); + console.log("Vault address:", vault); + console.log("NetworkRestakeDelegator:", networkRestakeDelegator); + console.log("VetoSlasher:", vetoSlasher); + } + + vm.stopBroadcast(); + } + + function _readVaultConfigs() internal view returns (VaultConfig[] memory configs) { + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/config/holesky/vaults.json"); + string memory json = vm.readFile(path); + + configs = abi.decode(vm.parseJson(json), (VaultConfig[])); + } + + function _readEpochDuration() internal view returns (uint48) { + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/config/holesky/parameters.json"); + string memory json = vm.readFile(path); + + return uint48(vm.parseJsonUint(json, ".epochDuration")); + } + + function _readVaultConfigurator() internal view returns (IVaultConfigurator) { + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/config/holesky/deployments.json"); + string memory json = vm.readFile(path); + + return IVaultConfigurator(vm.parseJsonAddress(json, ".symbiotic.vaultConfigurator")); + } +}