// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.27; import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {PauserRegistry} from "eigenlayer-contracts/src/contracts/permissions/PauserRegistry.sol"; import { IAllocationManagerTypes } from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; import {AVSDirectory} from "eigenlayer-contracts/src/contracts/core/AVSDirectory.sol"; import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol"; import {RewardsCoordinator} from "eigenlayer-contracts/src/contracts/core/RewardsCoordinator.sol"; import { PermissionController } from "eigenlayer-contracts/src/contracts/permissions/PermissionController.sol"; import {AllocationManager} from "eigenlayer-contracts/src/contracts/core/AllocationManager.sol"; import { IRewardsCoordinator, IRewardsCoordinatorTypes } from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; import {EmptyContract} from "eigenlayer-contracts/src/test/mocks/EmptyContract.sol"; import {StrategyBase} from "eigenlayer-contracts/src/contracts/strategies/StrategyBase.sol"; import {EigenStrategy} from "eigenlayer-contracts/src/contracts/strategies/EigenStrategy.sol"; import {EigenPodManagerMock} from "eigenlayer-contracts/src/test/mocks/EigenPodManagerMock.sol"; import {StrategyManager} from "eigenlayer-contracts/src/contracts/core/StrategyManager.sol"; import {IEigenPodManager} from "eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol"; import {ERC20FixedSupply} from "./ERC20FixedSupply.sol"; import {IServiceManager} from "../../src/interfaces/IServiceManager.sol"; import {VetoableSlasher} from "../../src/middleware/VetoableSlasher.sol"; import {IVetoableSlasher} from "../../src/interfaces/IVetoableSlasher.sol"; import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol"; import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol"; // Mocks import {RewardsCoordinatorMock} from "../mocks/RewardsCoordinatorMock.sol"; import {PermissionControllerMock} from "../mocks/PermissionControllerMock.sol"; import {DelegationManager} from "eigenlayer-contracts/src/contracts/core/DelegationManager.sol"; import "forge-std/Test.sol"; contract AVSDeployer is Test { Vm public cheats = Vm(VM_ADDRESS); ProxyAdmin public proxyAdmin; PauserRegistry public pauserRegistry; EmptyContract public emptyContract; // AVS contracts DataHavenServiceManager public serviceManager; DataHavenServiceManager public serviceManagerImplementation; VetoableSlasher public vetoableSlasher; RewardsRegistry public rewardsRegistry; // VetoableSlasher roles and parameters address public vetoCommitteeMember = address(uint160(uint256(keccak256("vetoCommitteeMember")))); uint32 public vetoWindowBlocks = 100; // 100 blocks veto window for tests // RewardsRegistry roles and parameters address public mockRewardsAgent = address(uint160(uint256(keccak256("rewardsAgent")))); // EigenLayer contracts StrategyManager public strategyManager; StrategyManager public strategyManagerImplementation; DelegationManager public delegationManager; DelegationManager public delegationManagerImplementation; EigenPodManagerMock public eigenPodManagerMock; AllocationManager public allocationManager; AllocationManager public allocationManagerImplementation; IStrategy public eigenStrategy; RewardsCoordinator public rewardsCoordinator; RewardsCoordinator public rewardsCoordinatorImplementation; RewardsCoordinatorMock public rewardsCoordinatorMock; PermissionControllerMock public permissionControllerMock; // Addresses address public proxyAdminOwner = address(uint160(uint256(keccak256("proxyAdminOwner")))); address public regularDeployer = address(uint160(uint256(keccak256("regularDeployer")))); address public avsOwner = address(uint160(uint256(keccak256("avsOwner")))); address public rewardsInitiator = address(uint160(uint256(keccak256("rewardsInitiator")))); address public pauser = address(uint160(uint256(keccak256("pauser")))); address public unpauser = address(uint160(uint256(keccak256("unpauser")))); address public rewardsUpdater = address(uint160(uint256(keccak256("rewardsUpdater")))); address public strategyOwner = address(uint160(uint256(keccak256("strategyOwner")))); // RewardsCoordinator constants uint32 public constant CALCULATION_INTERVAL_SECONDS = 7 days; uint32 public constant MAX_REWARDS_DURATION = 70 days; uint32 public constant MAX_RETROACTIVE_LENGTH = 84 days; uint32 public constant MAX_FUTURE_LENGTH = 28 days; uint32 public constant GENESIS_REWARDS_TIMESTAMP = 1712188800; /// @notice Delay in timestamp before a posted root can be claimed against uint32 public activationDelay = 7 days; /// @notice the commission for all operators across all AVSs uint16 public globalCommissionBips = 1000; // Mock strategies IERC20[] public rewardTokens; uint256 public mockTokenInitialSupply = 10e50; IStrategy[] public deployedStrategies; StrategyBase public strategyImplementation; IRewardsCoordinator.StrategyAndMultiplier[] public defaultStrategyAndMultipliers; function _deployMockEigenLayerAndAVS() internal { emptyContract = new EmptyContract(); // Deploy EigenLayer core contracts. cheats.startPrank(proxyAdminOwner); proxyAdmin = new ProxyAdmin(); cheats.stopPrank(); console.log("ProxyAdmin deployed"); cheats.startPrank(regularDeployer); address[] memory pausers = new address[](1); pausers[0] = pauser; pauserRegistry = new PauserRegistry(pausers, unpauser); eigenPodManagerMock = new EigenPodManagerMock(pauserRegistry); permissionControllerMock = new PermissionControllerMock(); rewardsCoordinatorMock = new RewardsCoordinatorMock(); cheats.stopPrank(); console.log("Mock EigenLayer contracts deployed"); // Deploying proxy contracts for AllocationManager and StrategyManager. // The `proxyAdmin` contract is set as the admin of the proxy contracts, // which will be later upgraded to the actual implementation. cheats.prank(regularDeployer); allocationManager = AllocationManager( address( new TransparentUpgradeableProxy(address(emptyContract), address(proxyAdmin), "") ) ); strategyManager = StrategyManager( address( new TransparentUpgradeableProxy(address(emptyContract), address(proxyAdmin), "") ) ); console.log("AllocationManager and StrategyManager proxy contracts deployed"); cheats.prank(regularDeployer); eigenStrategy = IStrategy(address(new EigenStrategy(strategyManager, pauserRegistry, "v-mock"))); console.log("EigenStrategy deployed"); // Deploying DelegationManager implementation and its proxy. cheats.prank(regularDeployer); delegationManagerImplementation = new DelegationManager( strategyManager, IEigenPodManager(address(eigenPodManagerMock)), allocationManager, pauserRegistry, permissionControllerMock, uint32(10), // MIN_WITHDRAWAL_DELAY_BLOCKS "v-mock" ); cheats.prank(regularDeployer); delegationManager = DelegationManager( address( new TransparentUpgradeableProxy( address(delegationManagerImplementation), address(proxyAdmin), "" ) ) ); // Deploying AllocationManager implementation and upgrading the proxy. cheats.prank(regularDeployer); allocationManagerImplementation = new AllocationManager( delegationManager, eigenStrategy, pauserRegistry, permissionControllerMock, uint32(7 days), // DEALLOCATION_DELAY uint32(1 days), // ALLOCATION_CONFIGURATION_DELAY "v-mock" ); cheats.prank(proxyAdminOwner); proxyAdmin.upgrade( ITransparentUpgradeableProxy(address(allocationManager)), address(allocationManagerImplementation) ); console.log("AllocationManager implementation deployed"); // Deploying StrategyManager implementation and its proxy. cheats.prank(regularDeployer); strategyManagerImplementation = new StrategyManager(allocationManager, delegationManager, pauserRegistry, "v-mock"); cheats.prank(proxyAdminOwner); uint256 allUnpaused = 0; proxyAdmin.upgradeAndCall( ITransparentUpgradeableProxy(address(strategyManager)), address(strategyManagerImplementation), abi.encodeWithSelector( StrategyManager.initialize.selector, strategyOwner, strategyOwner, allUnpaused ) ); console.log("StrategyManager implementation deployed"); // Deploying RewardsCoordinator implementation and its proxy. // When the proxy is deployed, the `initialize` function is called. cheats.startPrank(regularDeployer); IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams memory params = IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams({ delegationManager: delegationManager, strategyManager: IStrategyManager(address(strategyManager)), allocationManager: allocationManager, pauserRegistry: pauserRegistry, permissionController: permissionControllerMock, CALCULATION_INTERVAL_SECONDS: CALCULATION_INTERVAL_SECONDS, MAX_REWARDS_DURATION: MAX_REWARDS_DURATION, MAX_RETROACTIVE_LENGTH: MAX_RETROACTIVE_LENGTH, MAX_FUTURE_LENGTH: MAX_FUTURE_LENGTH, GENESIS_REWARDS_TIMESTAMP: GENESIS_REWARDS_TIMESTAMP, version: "v-mock" }); rewardsCoordinatorImplementation = new RewardsCoordinator(params); rewardsCoordinator = RewardsCoordinator( address( new TransparentUpgradeableProxy( address(rewardsCoordinatorImplementation), address(proxyAdmin), abi.encodeWithSelector( RewardsCoordinator.initialize.selector, msg.sender, 0, /*initialPausedStatus*/ rewardsUpdater, activationDelay, globalCommissionBips ) ) ) ); cheats.stopPrank(); console.log("RewardsCoordinator implementation deployed"); // Set up strategies before deploying the ServiceManager _setUpDefaultStrategiesAndMultipliers(); // Deploying ServiceManager implementation and its proxy. // When the proxy is deployed, the `initialize` function is called. cheats.startPrank(regularDeployer); serviceManagerImplementation = new DataHavenServiceManager( rewardsCoordinator, permissionControllerMock, allocationManager ); // Create array for validators strategies required by DataHavenServiceManager IStrategy[] memory validatorsStrategies = new IStrategy[](deployedStrategies.length); // For testing purposes, we'll use the deployed strategies for validators for (uint256 i = 0; i < deployedStrategies.length; i++) { validatorsStrategies[i] = deployedStrategies[i]; } serviceManager = DataHavenServiceManager( address( new TransparentUpgradeableProxy( address(serviceManagerImplementation), address(proxyAdmin), abi.encodeWithSelector( DataHavenServiceManager.initialise.selector, avsOwner, rewardsInitiator, validatorsStrategies, address(0) // This deployment does not use Snowbridge ) ) ) ); cheats.stopPrank(); console.log("ServiceManager implementation deployed"); // Deploy and configure the VetoableSlasher cheats.prank(regularDeployer); vetoableSlasher = new VetoableSlasher( allocationManager, serviceManager, vetoCommitteeMember, vetoWindowBlocks ); // Set the slasher in the ServiceManager cheats.prank(avsOwner); serviceManager.setSlasher(vetoableSlasher); console.log("VetoableSlasher deployed and configured"); // Deploy the RewardsRegistry contract cheats.prank(regularDeployer); rewardsRegistry = new RewardsRegistry(address(serviceManager), mockRewardsAgent); // Set the rewards registry in the ServiceManager cheats.prank(avsOwner); serviceManager.setRewardsRegistry(0, rewardsRegistry); console.log("RewardsRegistry deployed and configured"); } function _setUpDefaultStrategiesAndMultipliers() internal virtual { // Deploy mock tokens to be used for strategies. cheats.startPrank(strategyOwner); IERC20 token1 = new ERC20FixedSupply("dog wif hat", "MOCK1", mockTokenInitialSupply, address(this)); IERC20 token2 = new ERC20FixedSupply("jeo boden", "MOCK2", mockTokenInitialSupply, address(this)); IERC20 token3 = new ERC20FixedSupply("pepe wif avs", "MOCK3", mockTokenInitialSupply, address(this)); // Deploy mock strategies. strategyImplementation = new StrategyBase(IStrategyManager(address(strategyManager)), pauserRegistry, "v-mock"); deployedStrategies.push( StrategyBase( address( new TransparentUpgradeableProxy( address(strategyImplementation), address(proxyAdmin), abi.encodeWithSelector( StrategyBase.initialize.selector, token1, pauserRegistry ) ) ) ) ); deployedStrategies.push( StrategyBase( address( new TransparentUpgradeableProxy( address(strategyImplementation), address(proxyAdmin), abi.encodeWithSelector( StrategyBase.initialize.selector, token2, pauserRegistry ) ) ) ) ); deployedStrategies.push( StrategyBase( address( new TransparentUpgradeableProxy( address(strategyImplementation), address(proxyAdmin), abi.encodeWithSelector( StrategyBase.initialize.selector, token3, pauserRegistry ) ) ) ) ); cheats.stopPrank(); deployedStrategies = _sortArrayAsc(deployedStrategies); cheats.startPrank(strategyOwner); strategyManager.addStrategiesToDepositWhitelist(deployedStrategies); cheats.stopPrank(); defaultStrategyAndMultipliers.push( IRewardsCoordinatorTypes.StrategyAndMultiplier( IStrategy(address(deployedStrategies[0])), 1e18 ) ); defaultStrategyAndMultipliers.push( IRewardsCoordinatorTypes.StrategyAndMultiplier( IStrategy(address(deployedStrategies[1])), 2e18 ) ); defaultStrategyAndMultipliers.push( IRewardsCoordinatorTypes.StrategyAndMultiplier( IStrategy(address(deployedStrategies[2])), 3e18 ) ); } function _labelContracts() internal { cheats.label(address(emptyContract), "EmptyContract"); cheats.label(address(proxyAdmin), "ProxyAdmin"); cheats.label(address(pauserRegistry), "PauserRegistry"); cheats.label(address(delegationManager), "DelegationManager"); cheats.label(address(eigenPodManagerMock), "EigenPodManagerMock"); cheats.label(address(strategyManager), "StrategyManager"); cheats.label(address(rewardsCoordinatorMock), "RewardsCoordinatorMock"); cheats.label(address(allocationManager), "AllocationManager"); cheats.label(address(allocationManagerImplementation), "AllocationManagerImplementation"); cheats.label(address(serviceManager), "ServiceManager"); cheats.label(address(serviceManagerImplementation), "ServiceManagerImplementation"); cheats.label(address(vetoableSlasher), "VetoableSlasher"); } /// @dev Sort to ensure that the array is in ascending order for strategies function _sortArrayAsc( IStrategy[] memory arr ) internal pure returns (IStrategy[] memory) { uint256 l = arr.length; for (uint256 i = 0; i < l; i++) { for (uint256 j = i + 1; j < l; j++) { if (address(arr[i]) > address(arr[j])) { IStrategy temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } return arr; } function _incrementAddress( address start, uint256 inc ) internal pure returns (address) { return address(uint160(uint256(uint160(start) + inc))); } function _incrementBytes32( bytes32 start, uint256 inc ) internal pure returns (bytes32) { return bytes32(uint256(start) + inc); } function _setERC20Balance( address token, address user, uint256 amount ) internal { // Assumes balanceOf is in slot 0 (standard in OpenZeppelin ERC20) bytes32 slot = keccak256(abi.encode(user, uint256(0))); cheats.store(token, slot, bytes32(amount)); } }