datahaven/contracts/script/deploy/DeployLive.s.sol
undercover-cactus 6d323385d8
refactor: rename rewardsInitiator to snowbridgeInitiator (#476)
## Summary
Renames the rewardsInitiator state variable, modifier, internal check
function, setRewardsInitiator function, and RewardsInitiatorSet event in
DataHavenServiceManager to their snowbridgeInitiator-prefixed
equivalents, to better reflect the role of this address.

## Motivation
The previous rewardsInitiator naming was misleading — the address
filling this role is specifically the Snowbridge relayer/gateway.
Renaming it end-to-end clarifies intent and aligns the codebase with the
actual architecture.

## Changes
* DataHavenServiceManager.sol: renamed state variable, modifier,
internal check, setRewardsInitiator → -> setSnowbridgeInitiator,
RewardsInitiatorSet -> SnowbridgeInitiatorSet
* IDataHavenServiceManager.sol: updated event, function signature, and
NatSpec
* Deploy scripts & configs: updated field names across all environments
(anvil, testnet, stagenet, mainnet)
2026-03-24 12:41:36 +01:00

274 lines
11 KiB
Solidity

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.27;
import {DeployBase, ServiceManagerInitParams} from "./DeployBase.s.sol";
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
// Snowbridge imports for function signatures
import {BeefyClient} from "snowbridge/src/BeefyClient.sol";
import {AgentExecutor} from "snowbridge/src/AgentExecutor.sol";
import {IGatewayV2} from "snowbridge/src/v2/IGateway.sol";
// Logging import
import {Logging} from "../utils/Logging.sol";
// EigenLayer core contract imports for type casting
import {AllocationManager} from "eigenlayer-contracts/src/contracts/core/AllocationManager.sol";
import {AVSDirectory} from "eigenlayer-contracts/src/contracts/core/AVSDirectory.sol";
import {DelegationManager} from "eigenlayer-contracts/src/contracts/core/DelegationManager.sol";
import {RewardsCoordinator} from "eigenlayer-contracts/src/contracts/core/RewardsCoordinator.sol";
import {StrategyManager} from "eigenlayer-contracts/src/contracts/core/StrategyManager.sol";
import {
PermissionController
} from "eigenlayer-contracts/src/contracts/permissions/PermissionController.sol";
// OpenZeppelin imports for proxy creation
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import {
TransparentUpgradeableProxy
} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
/**
* @title DeployLive
* @notice Deployment script for live networks (hoodi testnet, ethereum mainnet)
* @dev References existing EigenLayer contracts on the target chain
*/
contract DeployLive is DeployBase {
string public networkName;
function run() public {
// Network detection and validation
networkName = vm.envString("NETWORK");
require(
bytes(networkName).length > 0,
"NETWORK environment variable required for live deployment"
);
_validateNetwork(networkName);
totalSteps = 4;
address avsOwnerEnv = vm.envOr("AVS_OWNER_ADDRESS", address(0));
require(
avsOwnerEnv != address(0),
"AVS_OWNER_ADDRESS env variable required for live deployments"
);
_executeSharedDeployment();
}
// Implementation of abstract functions from DeployBase
function _getNetworkName() internal view override returns (string memory) {
return networkName;
}
function _getDeploymentMode() internal view override returns (string memory) {
return string.concat("LIVE_", networkName);
}
function _setupEigenLayerContracts(
EigenLayerConfig memory config
) internal override returns (ProxyAdmin) {
Logging.logHeader("REFERENCING EXISTING EIGENLAYER CONTRACTS");
Logging.logSection(
string.concat("Referencing Existing EigenLayer Contracts on ", _getDeploymentMode())
);
// Reference existing EigenLayer contracts using addresses from config
delegation = DelegationManager(config.delegationManager);
strategyManager = StrategyManager(config.strategyManager);
avsDirectory = AVSDirectory(config.avsDirectory);
rewardsCoordinator = RewardsCoordinator(config.rewardsCoordinator);
allocationManager = AllocationManager(config.allocationManager);
permissionController = PermissionController(config.permissionController);
// Validate that contracts exist at the specified addresses
_validateContractExists(address(delegation), "DelegationManager");
_validateContractExists(address(strategyManager), "StrategyManager");
_validateContractExists(address(avsDirectory), "AVSDirectory");
_validateContractExists(address(rewardsCoordinator), "RewardsCoordinator");
_validateContractExists(address(allocationManager), "AllocationManager");
_validateContractExists(address(permissionController), "PermissionController");
Logging.logContractDeployed("DelegationManager (existing)", address(delegation));
Logging.logContractDeployed("StrategyManager (existing)", address(strategyManager));
Logging.logContractDeployed("AVSDirectory (existing)", address(avsDirectory));
Logging.logContractDeployed("RewardsCoordinator (existing)", address(rewardsCoordinator));
Logging.logContractDeployed("AllocationManager (existing)", address(allocationManager));
Logging.logContractDeployed(
"PermissionController (existing)", address(permissionController)
);
Logging.logStep("All EigenLayer contracts referenced successfully");
Logging.logFooter();
// Live deployments create their own ProxyAdmin (no existing one from EigenLayer deployment)
return ProxyAdmin(address(0)); // Will be created in _createServiceManagerProxy
}
function _createServiceManagerProxy(
DataHavenServiceManager implementation,
ProxyAdmin, // Ignored for live deployment
ServiceManagerInitParams memory params
) internal override returns (DataHavenServiceManager, ProxyAdmin) {
// Live deployment creates its own ProxyAdmin for the service manager
vm.broadcast(_deployerPrivateKey);
ProxyAdmin proxyAdmin = new ProxyAdmin();
Logging.logContractDeployed("ProxyAdmin", address(proxyAdmin));
// Transfer ProxyAdmin ownership to AVS owner so upgrades can only be performed by AVS owner
vm.broadcast(_deployerPrivateKey);
proxyAdmin.transferOwnership(params.avsOwner);
Logging.logStep("ProxyAdmin ownership transferred to AVS owner");
vm.broadcast(_deployerPrivateKey);
bytes memory initData = abi.encodeWithSelector(
DataHavenServiceManager.initialize.selector,
params.avsOwner,
params.snowbridgeInitiator,
params.validatorsStrategiesAndMultipliers,
params.gateway,
params.validatorSetSubmitter,
params.initialVersion
);
TransparentUpgradeableProxy proxy =
new TransparentUpgradeableProxy(address(implementation), address(proxyAdmin), initData);
return (DataHavenServiceManager(address(proxy)), proxyAdmin);
}
function _outputDeployedAddresses(
BeefyClient beefyClient,
AgentExecutor agentExecutor,
IGatewayV2 gateway,
DataHavenServiceManager serviceManager,
DataHavenServiceManager serviceManagerImplementation,
address rewardsAgent,
ProxyAdmin proxyAdmin
) internal override {
Logging.logHeader("DEPLOYMENT SUMMARY");
Logging.logSection("Snowbridge Contracts + Rewards Agent");
Logging.logContractDeployed("BeefyClient", address(beefyClient));
Logging.logContractDeployed("AgentExecutor", address(agentExecutor));
Logging.logContractDeployed("Gateway", address(gateway));
Logging.logContractDeployed("RewardsAgent", rewardsAgent);
Logging.logSection("DataHaven Contracts");
Logging.logContractDeployed("ServiceManager", address(serviceManager));
Logging.logSection(
string.concat("EigenLayer Core Contracts (Existing on ", _getDeploymentMode(), ")")
);
Logging.logContractDeployed("DelegationManager", address(delegation));
Logging.logContractDeployed("StrategyManager", address(strategyManager));
Logging.logContractDeployed("AVSDirectory", address(avsDirectory));
Logging.logContractDeployed("RewardsCoordinator", address(rewardsCoordinator));
Logging.logContractDeployed("AllocationManager", address(allocationManager));
Logging.logContractDeployed("PermissionController", address(permissionController));
Logging.logFooter();
// Write to deployment file for future reference
string memory network = _getNetworkName();
string memory deploymentPath =
string.concat(vm.projectRoot(), "/deployments/", network, ".json");
// Create directory if it doesn't exist
vm.createDir(string.concat(vm.projectRoot(), "/deployments"), true);
// Create JSON with deployed addresses
string memory json = "{";
json = string.concat(json, '"network": "', network, '",');
// Snowbridge contracts
json = string.concat(json, '"BeefyClient": "', vm.toString(address(beefyClient)), '",');
json = string.concat(json, '"AgentExecutor": "', vm.toString(address(agentExecutor)), '",');
json = string.concat(json, '"Gateway": "', vm.toString(address(gateway)), '",');
json =
string.concat(json, '"ServiceManager": "', vm.toString(address(serviceManager)), '",');
json = string.concat(
json,
'"ServiceManagerImplementation": "',
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)
json = string.concat(json, '"DelegationManager": "', vm.toString(address(delegation)), '",');
json = string.concat(
json, '"StrategyManager": "', vm.toString(address(strategyManager)), '",'
);
json = string.concat(json, '"AVSDirectory": "', vm.toString(address(avsDirectory)), '",');
json = string.concat(
json, '"RewardsCoordinator": "', vm.toString(address(rewardsCoordinator)), '",'
);
json = string.concat(
json, '"AllocationManager": "', vm.toString(address(allocationManager)), '",'
);
json = string.concat(
json, '"PermissionController": "', vm.toString(address(permissionController)), '"'
);
json = string.concat(json, "}");
// Write to file
vm.writeFile(deploymentPath, json);
Logging.logInfo(string.concat("Deployment info saved to: ", deploymentPath));
}
// LIVE DEPLOYMENT FUNCTIONS
/**
* @notice Validate that the network is in the supported allowlist
* @dev Supported networks:
* - "hoodi", "stagenet-hoodi", "testnet-hoodi" (Hoodi testnet)
* - "ethereum", "mainnet-ethereum" (Ethereum mainnet)
*/
function _validateNetwork(
string memory network
) internal pure {
bytes32 h = keccak256(bytes(network));
if (
h == keccak256("hoodi") || h == keccak256("stagenet-hoodi")
|| h == keccak256("testnet-hoodi") || h == keccak256("mainnet-ethereum")
|| h == keccak256("ethereum")
) {
return;
}
revert(
string.concat(
"Unsupported network: ",
network,
". Supported: hoodi, stagenet-hoodi, testnet-hoodi, ethereum, mainnet-ethereum"
)
);
}
/**
* @notice Validate that a contract exists at the given address
*/
function _validateContractExists(
address contractAddress,
string memory contractName
) internal view {
require(
contractAddress != address(0), string.concat(contractName, " address cannot be zero")
);
uint256 codeSize;
assembly {
codeSize := extcodesize(contractAddress)
}
require(
codeSize > 0,
string.concat(
"No contract found at ", contractName, " address: ", vm.toString(contractAddress)
)
);
}
}