diff --git a/contracts/script/deploy/DeployBase.s.sol b/contracts/script/deploy/DeployBase.s.sol index 587bcd81..dab827e2 100644 --- a/contracts/script/deploy/DeployBase.s.sol +++ b/contracts/script/deploy/DeployBase.s.sol @@ -43,6 +43,8 @@ struct ServiceManagerInitParams { address rewardsInitiator; address[] validatorsStrategies; address gateway; + string initialVersion; + address versionUpdater; } // Struct to store more detailed strategy information @@ -144,7 +146,8 @@ abstract contract DeployBase is Script, DeployParams, Accounts { gateway, serviceManager, serviceManagerImplementation, - rewardsAgentAddress + rewardsAgentAddress, + proxyAdmin ); _outputRewardsAgentInfo(rewardsAgentAddress, snowbridgeConfig.rewardsMessageOrigin); @@ -245,12 +248,18 @@ abstract contract DeployBase is Script, DeployParams, Accounts { "ServiceManager Implementation", address(serviceManagerImplementation) ); + // Read version from environment variable (passed by TypeScript wrapper) + string memory version = vm.envOr("DATAHAVEN_VERSION", string("0.1.0")); + console.log("| Version: %s", version); + // Create service manager initialisation parameters struct ServiceManagerInitParams memory initParams = ServiceManagerInitParams({ avsOwner: avsConfig.avsOwner, rewardsInitiator: avsConfig.rewardsInitiator, validatorsStrategies: avsConfig.validatorsStrategies, - gateway: address(gateway) + gateway: address(gateway), + initialVersion: version, + versionUpdater: _deployer }); // Create the service manager proxy (different logic for local vs testnet) @@ -290,7 +299,8 @@ abstract contract DeployBase is Script, DeployParams, Accounts { IGatewayV2 gateway, DataHavenServiceManager serviceManager, DataHavenServiceManager serviceManagerImplementation, - address rewardsAgent + address rewardsAgent, + ProxyAdmin proxyAdmin ) internal virtual; /** diff --git a/contracts/script/deploy/DeployImplementation.s.sol b/contracts/script/deploy/DeployImplementation.s.sol new file mode 100644 index 00000000..79df1c12 --- /dev/null +++ b/contracts/script/deploy/DeployImplementation.s.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.27; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; + +// DataHaven imports +import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol"; + +// EigenLayer imports +import {RewardsCoordinator} from "eigenlayer-contracts/src/contracts/core/RewardsCoordinator.sol"; +import {AllocationManager} from "eigenlayer-contracts/src/contracts/core/AllocationManager.sol"; + +// OpenZeppelin imports +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { + ITransparentUpgradeableProxy +} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +/** + * @title DeployImplementation + * @notice Script for deploying implementation contracts and upgrading proxies + */ +contract DeployImplementation is Script { + function run() public { + // This script is designed to be called with specific function selectors + // Use forge script with --sig "functionName()" to call specific functions + } + + /** + * @notice Deploy new ServiceManager implementation + */ + function deployServiceManagerImpl() public { + console.log("Deploying ServiceManager Implementation..."); + + // Get constructor parameters from environment variables + address rewardsCoordinator = vm.envAddress("REWARDS_COORDINATOR"); + address allocationManager = vm.envAddress("ALLOCATION_MANAGER"); + + require(rewardsCoordinator != address(0), "REWARDS_COORDINATOR not set"); + require(allocationManager != address(0), "ALLOCATION_MANAGER not set"); + + vm.broadcast(); + DataHavenServiceManager serviceManagerImpl = new DataHavenServiceManager( + RewardsCoordinator(rewardsCoordinator), AllocationManager(allocationManager) + ); + + console.log("ServiceManager Implementation deployed at:", address(serviceManagerImpl)); + } + + /** + * @notice Update ServiceManager proxy to point to new implementation + * @dev This is the legacy upgrade method without version update + */ + function updateServiceManagerProxy() public { + console.log("Updating ServiceManager proxy..."); + + // Get addresses from environment variables + address serviceManager = vm.envAddress("SERVICE_MANAGER"); + address newImplementation = vm.envAddress("SERVICE_MANAGER_IMPL"); + address proxyAdmin = vm.envAddress("PROXY_ADMIN"); + + require(serviceManager != address(0), "SERVICE_MANAGER not set"); + require(newImplementation != address(0), "SERVICE_MANAGER_IMPL not set"); + require(newImplementation.code.length > 0, "SERVICE_MANAGER_IMPL is not a contract"); + require(proxyAdmin != address(0), "PROXY_ADMIN not set"); + + vm.broadcast(); + ProxyAdmin(proxyAdmin) + .upgrade(ITransparentUpgradeableProxy(payable(serviceManager)), newImplementation); + + console.log("ServiceManager proxy updated to new implementation:", newImplementation); + } + + /** + * @notice Update ServiceManager proxy and set version in one transaction + * @dev Uses upgradeAndCall to combine upgrade and version update, saving gas + */ + function updateServiceManagerProxyWithVersion() public { + console.log("Updating ServiceManager proxy with version..."); + + // Get addresses and version from environment variables + address serviceManager = vm.envAddress("SERVICE_MANAGER"); + address newImplementation = vm.envAddress("SERVICE_MANAGER_IMPL"); + address proxyAdmin = vm.envAddress("PROXY_ADMIN"); + string memory newVersion = vm.envString("NEW_VERSION"); + + require(serviceManager != address(0), "SERVICE_MANAGER not set"); + require(newImplementation != address(0), "SERVICE_MANAGER_IMPL not set"); + require(newImplementation.code.length > 0, "SERVICE_MANAGER_IMPL is not a contract"); + require(proxyAdmin != address(0), "PROXY_ADMIN not set"); + require(bytes(newVersion).length > 0, "NEW_VERSION not set"); + + // Encode the updateVersion call + bytes memory data = abi.encodeWithSignature("updateVersion(string)", newVersion); + + vm.broadcast(); + ProxyAdmin(proxyAdmin).upgradeAndCall( + ITransparentUpgradeableProxy(payable(serviceManager)), newImplementation, data + ); + + console.log("ServiceManager proxy updated to:", newImplementation); + console.log("Version updated to:", newVersion); + } +} diff --git a/contracts/script/deploy/DeployLive.s.sol b/contracts/script/deploy/DeployLive.s.sol index 74c85f17..fa6e1796 100644 --- a/contracts/script/deploy/DeployLive.s.sol +++ b/contracts/script/deploy/DeployLive.s.sol @@ -121,7 +121,9 @@ contract DeployLive is DeployBase { params.avsOwner, params.rewardsInitiator, params.validatorsStrategies, - params.gateway + params.gateway, + params.initialVersion, + params.versionUpdater ); TransparentUpgradeableProxy proxy = @@ -136,7 +138,8 @@ contract DeployLive is DeployBase { IGatewayV2 gateway, DataHavenServiceManager serviceManager, DataHavenServiceManager serviceManagerImplementation, - address rewardsAgent + address rewardsAgent, + ProxyAdmin proxyAdmin ) internal override { Logging.logHeader("DEPLOYMENT SUMMARY"); @@ -185,6 +188,7 @@ contract DeployLive is DeployBase { vm.toString(address(serviceManagerImplementation)), '",' ); + json = string.concat(json, '"ProxyAdmin": "', vm.toString(address(proxyAdmin)), '",'); json = string.concat(json, '"RewardsAgent": "', vm.toString(rewardsAgent), '",'); // EigenLayer contracts (existing on live network) diff --git a/contracts/script/deploy/DeployLocal.s.sol b/contracts/script/deploy/DeployLocal.s.sol index 8d122912..93fc43a8 100644 --- a/contracts/script/deploy/DeployLocal.s.sol +++ b/contracts/script/deploy/DeployLocal.s.sol @@ -207,7 +207,9 @@ contract DeployLocal is DeployBase { params.avsOwner, params.rewardsInitiator, params.validatorsStrategies, - params.gateway + params.gateway, + params.initialVersion, + params.versionUpdater ); TransparentUpgradeableProxy proxy = @@ -222,7 +224,8 @@ contract DeployLocal is DeployBase { IGatewayV2 gateway, DataHavenServiceManager serviceManager, DataHavenServiceManager serviceManagerImplementation, - address rewardsAgent + address rewardsAgent, + ProxyAdmin proxyAdmin ) internal override { Logging.logHeader("DEPLOYMENT SUMMARY"); @@ -283,6 +286,7 @@ contract DeployLocal is DeployBase { vm.toString(address(serviceManagerImplementation)), '",' ); + json = string.concat(json, '"ProxyAdmin": "', vm.toString(address(proxyAdmin)), '",'); json = string.concat(json, '"RewardsAgent": "', vm.toString(rewardsAgent), '",'); // EigenLayer contracts