diff --git a/src/ServiceManagerBase.sol b/src/ServiceManagerBase.sol index 47ac07f1..74d47510 100644 --- a/src/ServiceManagerBase.sol +++ b/src/ServiceManagerBase.sol @@ -14,7 +14,6 @@ import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol"; import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol"; import {BitmapUtils} from "./libraries/BitmapUtils.sol"; import {LibMergeSort} from "./libraries/LibMergeSort.sol"; -import {console} from "forge-std/Test.sol"; /** * @title Minimal implementation of a ServiceManager-type contract. @@ -24,6 +23,8 @@ import {console} from "forge-std/Test.sol"; abstract contract ServiceManagerBase is ServiceManagerBaseStorage { using BitmapUtils for *; + uint256 public constant SLASHER_PROPOSAL_DELAY = 7 days; + /// @notice when applied to a function, only allows the RegistryCoordinator to call it modifier onlyRegistryCoordinator() { require( @@ -177,12 +178,25 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage { } /** - * @notice Sets the slasher address + * @notice Proposes a new slasher address * @param newSlasher The new slasher address * @dev only callable by the owner */ - function setSlasher(address newSlasher) external onlyOwner { - _setSlasher(newSlasher); + function proposeNewSlasher(address newSlasher) external onlyOwner { + _proposeNewSlasher(newSlasher); + } + + /** + * @notice Accepts the proposed slasher address after the delay period + * @dev only callable by the owner + */ + function acceptProposedSlasher() external onlyOwner { + require( + block.timestamp >= slasherProposalTimestamp + SLASHER_PROPOSAL_DELAY, + "ServiceManager: Slasher proposal delay not met" + ); + _setSlasher(proposedSlasher); + delete proposedSlasher; } /** @@ -342,6 +356,12 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage { rewardsInitiator = newRewardsInitiator; } + function _proposeNewSlasher(address newSlasher) internal { + proposedSlasher = newSlasher; + slasherProposalTimestamp = block.timestamp; + emit SlasherProposed(newSlasher, slasherProposalTimestamp); + } + function _setSlasher(address newSlasher) internal { emit SlasherUpdated(slasher, newSlasher); slasher = newSlasher; @@ -425,6 +445,10 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage { return address(_avsDirectory); } + function allocationManager() external view override returns (address) { + return address(_allocationManager); + } + function _checkRewardsInitiator() internal view { require( msg.sender == rewardsInitiator, diff --git a/src/ServiceManagerBaseStorage.sol b/src/ServiceManagerBaseStorage.sol index 71d54d98..0bc52090 100644 --- a/src/ServiceManagerBaseStorage.sol +++ b/src/ServiceManagerBaseStorage.sol @@ -40,6 +40,13 @@ abstract contract ServiceManagerBaseStorage is IServiceManager, OwnableUpgradeab /// @notice The address of the slasher account address public slasher; + /// @notice The address of the proposed slasher account + address public proposedSlasher; + + /// @notice The timestamp when the slasher was proposed + uint256 public slasherProposalTimestamp; + + /// @notice Boolean indicating if the migration has been finalized bool public migrationFinalized; /// @notice Sets the (immutable) `_avsDirectory`, `_rewardsCoordinator`, `_registryCoordinator`, `_stakeRegistry`, and `_allocationManager` addresses @@ -58,5 +65,5 @@ abstract contract ServiceManagerBaseStorage is IServiceManager, OwnableUpgradeab } // storage gap for upgradeability - uint256[48] private __GAP; + uint256[46] private __GAP; } diff --git a/src/StakeRegistry.sol b/src/StakeRegistry.sol index 9d4da097..e1e4e449 100644 --- a/src/StakeRegistry.sol +++ b/src/StakeRegistry.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.12; import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; import {IAVSDirectory, OperatorSet} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol"; +import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; import {IServiceManager} from "./interfaces/IServiceManager.sol"; import {StakeRegistryStorage, IStrategy} from "./StakeRegistryStorage.sol"; @@ -229,6 +230,18 @@ contract StakeRegistry is StakeRegistryStorage { _setMinimumStakeForQuorum(quorumNumber, minimumStake); } + /** + * @notice Sets the stake type for the registry + * @param _stakeType The type of stake to track (TOTAL_DELEGATED, TOTAL_SLASHABLE, or BOTH) + */ + function setStakeType(StakeType _stakeType) external onlyCoordinatorOwner { + _setStakeType(_stakeType); + } + + + function setSlashableStakeLookahead(uint32 _lookAheadPeriod) external onlyCoordinatorOwner { + _setLookAheadPeriod(_lookAheadPeriod); + } /** * @notice Adds strategies and weights to the quorum * @dev Checks to make sure that the *same* strategy cannot be added multiple times (checks against both against existing and new strategies). @@ -491,15 +504,17 @@ contract StakeRegistry is StakeRegistryStorage { uint256 stratsLength = strategyParamsLength(quorumNumber); StrategyParams memory strategyAndMultiplier; - uint256[] memory strategyShares; - // = delegation.getDelegatableShares(operator, strategiesPerQuorum[quorumNumber]); + address[] memory operators = new address[](1); + operators[0] = operator; + uint32 beforeTimestamp = uint32(block.timestamp + slashableStakeLookAhead); + (uint256[][] memory strategyShares, ) = IAllocationManager(serviceManager.allocationManager()).getMinDelegatedAndSlashableOperatorShares(OperatorSet(address(serviceManager), quorumNumber), operators ,strategiesPerQuorum[quorumNumber], beforeTimestamp); for (uint256 i = 0; i < stratsLength; i++) { // accessing i^th StrategyParams struct for the quorumNumber strategyAndMultiplier = strategyParams[quorumNumber][i]; // add the weight from the shares for this strategy to the total weight - if (strategyShares[i] > 0) { - weight += uint96(strategyShares[i] * strategyAndMultiplier.multiplier / WEIGHTING_DIVISOR); + if (strategyShares[i][0] > 0) { + weight += uint96(strategyShares[i][0] * strategyAndMultiplier.multiplier / WEIGHTING_DIVISOR); } } @@ -731,6 +746,27 @@ contract StakeRegistry is StakeRegistryStorage { return indices; } + /** + * @notice Sets the stake type for the registry + * @param _stakeType The type of stake to track (TOTAL_DELEGATED, TOTAL_SLASHABLE, or BOTH) + */ + function _setStakeType(StakeType _stakeType) internal { + StakeType oldStakeType = stakeType; + stakeType = _stakeType; + emit StakeTypeSet(oldStakeType, _stakeType); + } + + /** + * @notice Sets the look ahead time for checking operator shares + * @param _lookAheadDays The number of days to look ahead when checking shares + */ + function _setLookAheadPeriod(uint32 _lookAheadDays) internal { + uint32 oldLookAheadDays = slashableStakeLookAhead; + slashableStakeLookAhead = _lookAheadDays; + emit LookAheadPeriodChanged(oldLookAheadDays, _lookAheadDays); + } + + function _checkRegistryCoordinator() internal view { require( msg.sender == address(registryCoordinator), diff --git a/src/StakeRegistryStorage.sol b/src/StakeRegistryStorage.sol index f76608d2..7fea4fa2 100644 --- a/src/StakeRegistryStorage.sol +++ b/src/StakeRegistryStorage.sol @@ -52,6 +52,9 @@ abstract contract StakeRegistryStorage is IStakeRegistry { mapping(uint8 => StrategyParams[]) public strategyParams; mapping(uint8 => IStrategy[]) public strategiesPerQuorum; + StakeType public stakeType; + + uint32 public slashableStakeLookAhead; constructor( IRegistryCoordinator _registryCoordinator, @@ -67,5 +70,5 @@ abstract contract StakeRegistryStorage is IStakeRegistry { // storage gap for upgradeability // slither-disable-next-line shadowing-state - uint256[45] private __GAP; + uint256[44] private __GAP; } diff --git a/src/interfaces/IServiceManager.sol b/src/interfaces/IServiceManager.sol index 5057525e..6c2bcf94 100644 --- a/src/interfaces/IServiceManager.sol +++ b/src/interfaces/IServiceManager.sol @@ -5,6 +5,7 @@ import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces import {IServiceManagerUI} from "./IServiceManagerUI.sol"; import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol"; import {IAllocationManagerTypes} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; /** * @title Minimal interface for a ServiceManager-type contract that forms the single point for an AVS to push updates to EigenLayer @@ -50,4 +51,5 @@ interface IServiceManager is IServiceManagerUI { // EVENTS event RewardsInitiatorUpdated(address prevRewardsInitiator, address newRewardsInitiator); event SlasherUpdated(address prevSlasher, address newSlasher); + event SlasherProposed(address newSlasher, uint256 slasherProposalTimestamp); } diff --git a/src/interfaces/IServiceManagerUI.sol b/src/interfaces/IServiceManagerUI.sol index 92cdce9c..7be5a3f0 100644 --- a/src/interfaces/IServiceManagerUI.sol +++ b/src/interfaces/IServiceManagerUI.sol @@ -58,4 +58,7 @@ interface IServiceManagerUI { /// @notice Returns the EigenLayer AVSDirectory contract. function avsDirectory() external view returns (address); + + /// @notice Returns the EigenLayer AllocationManager contract. + function allocationManager() external view returns (address); } diff --git a/src/interfaces/ISlasher.sol b/src/interfaces/ISlasher.sol new file mode 100644 index 00000000..e2d128f1 --- /dev/null +++ b/src/interfaces/ISlasher.sol @@ -0,0 +1,45 @@ + +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.12; + +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; + +interface ISlasherEvents { + event SlashingRequested( + uint256 indexed requestId, + address indexed operator, + uint32 indexed operatorSetId, + uint256 wadToSlash, + string description + ); + + event SlashingRequestCancelled(uint256 indexed requestId); + + event OperatorSlashed( + uint256 indexed slashingRequestId, + address indexed operator, + uint32 indexed operatorSetId, + IStrategy[] strategies, + uint256 wadToSlash, + string description + ); +} + +interface ISlasherTypes { + enum SlashingStatus { + Null, + Requested, + Completed, + Cancelled + } + + struct SlashingRequest { + IAllocationManager.SlashingParams params; + uint256 requestTimestamp; + SlashingStatus status; + } + +} + +interface ISlasher is ISlasherEvents, ISlasherTypes{} diff --git a/src/interfaces/IStakeRegistry.sol b/src/interfaces/IStakeRegistry.sol index 044ccd58..c4ebd195 100644 --- a/src/interfaces/IStakeRegistry.sol +++ b/src/interfaces/IStakeRegistry.sol @@ -11,6 +11,12 @@ import {IRegistry} from "./IRegistry.sol"; * @author Layr Labs, Inc. */ interface IStakeRegistry is IRegistry { + + enum StakeType { + TOTAL_DELEGATED, + TOTAL_SLASHABLE, + BOTH + } // DATA STRUCTURES @@ -42,6 +48,13 @@ interface IStakeRegistry is IRegistry { uint8 quorumNumber, uint96 stake ); + + + /// @notice emitted when the look ahead time for checking operator shares is updated + event LookAheadPeriodChanged(uint32 oldLookAheadDays, uint32 newLookAheadDays); + + /// @notice emitted when the stake type is updated + event StakeTypeSet(StakeType previousStakeType, StakeType newStakeType); /// @notice emitted when the minimum stake for a quorum is updated event MinimumStakeForQuorumUpdated(uint8 indexed quorumNumber, uint96 minimumStake); /// @notice emitted when a new quorum is created diff --git a/src/slashers/InstantSlasher.sol b/src/slashers/InstantSlasher.sol new file mode 100644 index 00000000..b30d5881 --- /dev/null +++ b/src/slashers/InstantSlasher.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.12; + +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {SlasherBase} from "./base/SlasherBase.sol"; + +contract InstantSlasher is SlasherBase { + + function initialize(address _serviceManager, address _slasher) external initializer { + __SlasherBase_init(_serviceManager, _slasher); + } + + function fulfillSlashingRequest( + IAllocationManager.SlashingParams memory _slashingParams + ) external virtual onlySlasher { + uint256 requestId = nextRequestId++; + _fulfillSlashingRequest(requestId, _slashingParams); + } + + +} \ No newline at end of file diff --git a/src/slashers/SimpleSlasher.sol b/src/slashers/SimpleSlasher.sol deleted file mode 100644 index faa4f49b..00000000 --- a/src/slashers/SimpleSlasher.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.12; - -import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; -import {IServiceManager} from "../interfaces/IServiceManager.sol"; -import {SlasherStorage} from "./SlasherStorage.sol"; -import {IAllocationManagerTypes} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; -import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; - -contract SimpleSlasher is Initializable, SlasherStorage { - function initialize(address _serviceManager) public initializer { - serviceManager = _serviceManager; - } - - function slashOperator( - address operator, - uint32 operatorSetId, - IStrategy[] memory strategies, - uint256 wadToSlash, - string memory description - ) external { - - IAllocationManagerTypes.SlashingParams memory params = IAllocationManagerTypes.SlashingParams({ - operator: operator, - operatorSetId: operatorSetId, - strategies: strategies, - wadToSlash: wadToSlash, - description: description - }); - - IServiceManager(serviceManager).slashOperator(params); - } -} diff --git a/src/slashers/SlasherStorage.sol b/src/slashers/SlasherStorage.sol deleted file mode 100644 index 1b3d61de..00000000 --- a/src/slashers/SlasherStorage.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.12; - -contract SlasherStorage { - address public serviceManager; - - uint256[49] private __gap; -} \ No newline at end of file diff --git a/src/slashers/VetoableSlasher.sol b/src/slashers/VetoableSlasher.sol new file mode 100644 index 00000000..b65442b6 --- /dev/null +++ b/src/slashers/VetoableSlasher.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.12; + +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import {SlasherBase} from "./base/SlasherBase.sol"; +import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; + +contract VetoableSlashing is SlasherBase { + uint256 public constant VETO_PERIOD = 3 days; + address public vetoCommittee; + + mapping(uint256 => SlashingRequest) public slashingRequests; + + modifier onlyVetoCommittee() { + _checkVetoCommittee(msg.sender); + _; + } + + function initialize( + address _serviceManager, + address _vetoCommittee, + address _slasher + ) external virtual initializer { + __SlasherBase_init(_serviceManager, _slasher); + vetoCommittee = _vetoCommittee; + } + + function queueSlashingRequest(IAllocationManager.SlashingParams memory params) external virtual onlySlasher { + _queueSlashingRequest(params); + } + + function cancelSlashingRequest(uint256 requestId) external virtual onlyVetoCommittee { + require( + block.timestamp < slashingRequests[requestId].requestTimestamp + VETO_PERIOD, + "VetoableSlashing: veto period has passed" + ); + require(slashingRequests[requestId].status == SlashingStatus.Requested, "VetoableSlashing: request is not in Requested status"); + + _cancelSlashingRequest(requestId); + } + + function fulfillSlashingRequest(uint256 requestId) external virtual onlySlasher { + SlashingRequest storage request = slashingRequests[requestId]; + require( + block.timestamp >= request.requestTimestamp + VETO_PERIOD, + "VetoableSlashing: veto period has not passed" + ); + require(request.status == SlashingStatus.Requested, "VetoableSlashing: request has been cancelled"); + + request.status = SlashingStatus.Completed; + + _fulfillSlashingRequest( + requestId, + request.params + ); + } + + function _queueSlashingRequest(IAllocationManager.SlashingParams memory params) internal virtual { + uint256 requestId = nextRequestId++; + slashingRequests[requestId] = SlashingRequest({ + params: params, + requestTimestamp: block.timestamp, + status: SlashingStatus.Requested + }); + + emit SlashingRequested(requestId, params.operator, params.operatorSetId, params.wadToSlash, params.description); + } + + function _cancelSlashingRequest(uint256 requestId) internal virtual { + slashingRequests[requestId].status = SlashingStatus.Cancelled; + emit SlashingRequestCancelled(requestId); + } + + function _checkVetoCommittee(address account) internal view virtual { + require(account == vetoCommittee, "VetoableSlashing: caller is not the veto committee"); + } +} \ No newline at end of file diff --git a/src/slashers/base/SlasherBase.sol b/src/slashers/base/SlasherBase.sol new file mode 100644 index 00000000..c62513d3 --- /dev/null +++ b/src/slashers/base/SlasherBase.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.12; + +import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; +import {IServiceManager} from "../../interfaces/IServiceManager.sol"; +import {SlasherStorage} from "./SlasherStorage.sol"; +import {IAllocationManagerTypes, IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; + +abstract contract SlasherBase is Initializable, SlasherStorage { + + modifier onlySlasher() { + _checkSlasher(msg.sender); + _; + } + + function __SlasherBase_init(address _serviceManager, address _slasher) internal onlyInitializing { + serviceManager = _serviceManager; + slasher = _slasher; + } + + function _fulfillSlashingRequest( + uint256 _requestId, + IAllocationManager.SlashingParams memory _params + ) internal virtual { + IServiceManager(serviceManager).slashOperator(_params); + emit OperatorSlashed(_requestId, _params.operator, _params.operatorSetId, _params.strategies, _params.wadToSlash, _params.description); + } + + function _checkSlasher(address account) internal view virtual { + require(account == slasher, "InstantSlasher: caller is not the slasher"); + } +} + + + + diff --git a/src/slashers/base/SlasherStorage.sol b/src/slashers/base/SlasherStorage.sol new file mode 100644 index 00000000..1024811a --- /dev/null +++ b/src/slashers/base/SlasherStorage.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.12; + +import {ISlasher} from "../../interfaces/ISlasher.sol"; +contract SlasherStorage is ISlasher { + address public serviceManager; + address public slasher; + uint256 public nextRequestId; + + uint256[47] private __gap; +} \ No newline at end of file diff --git a/src/unaudited/ECDSAServiceManagerBase.sol b/src/unaudited/ECDSAServiceManagerBase.sol index 3d30f451..facb6813 100644 --- a/src/unaudited/ECDSAServiceManagerBase.sol +++ b/src/unaudited/ECDSAServiceManagerBase.sol @@ -23,6 +23,9 @@ abstract contract ECDSAServiceManagerBase is /// @notice Address of the AVS directory contract, which manages AVS-related data for registered operators. address public immutable avsDirectory; + /// @notice Address of the AllocationManager contract + address public immutable allocationManager; + /// @notice Address of the rewards coordinator contract, which handles rewards distributions. address internal immutable rewardsCoordinator; @@ -70,12 +73,14 @@ abstract contract ECDSAServiceManagerBase is address _avsDirectory, address _stakeRegistry, address _rewardsCoordinator, - address _delegationManager + address _delegationManager, + address _allocationManager ) { avsDirectory = _avsDirectory; stakeRegistry = _stakeRegistry; rewardsCoordinator = _rewardsCoordinator; delegationManager = _delegationManager; + allocationManager = _allocationManager; _disableInitializers(); } diff --git a/src/unaudited/ECDSAStakeRegistry.sol b/src/unaudited/ECDSAStakeRegistry.sol index a8dff79a..b333d504 100644 --- a/src/unaudited/ECDSAStakeRegistry.sol +++ b/src/unaudited/ECDSAStakeRegistry.sol @@ -248,12 +248,10 @@ contract ECDSAStakeRegistry is for (uint256 i; i < strategyParams.length; i++) { strategies[i] = strategyParams[i].strategy; } - uint256[] memory shares; - /// TODO: FIX - // = DELEGATION_MANAGER.getOperatorShares( - // _operator, - // strategies - // ); + uint256[] memory shares = DELEGATION_MANAGER.getOperatorShares( + _operator, + strategies + ); for (uint256 i; i < strategyParams.length; i++) { weight += shares[i] * strategyParams[i].multiplier; } diff --git a/test/mocks/AVSDirectoryMock.sol b/test/mocks/AVSDirectoryMock.sol index a6bf2a3c..597a09a1 100644 --- a/test/mocks/AVSDirectoryMock.sol +++ b/test/mocks/AVSDirectoryMock.sol @@ -170,4 +170,4 @@ contract AVSDirectoryMock is IAVSDirectory { ) external {} function addStrategiesToOperatorSet(uint32 operatorSetId, IStrategy[] calldata strategies) external {} -} \ No newline at end of file +} diff --git a/test/mocks/ECDSAServiceManagerMock.sol b/test/mocks/ECDSAServiceManagerMock.sol index 5be1d82d..2c3c872b 100644 --- a/test/mocks/ECDSAServiceManagerMock.sol +++ b/test/mocks/ECDSAServiceManagerMock.sol @@ -9,13 +9,15 @@ contract ECDSAServiceManagerMock is ECDSAServiceManagerBase { address _avsDirectory, address _stakeRegistry, address _rewardsCoordinator, - address _delegationManager + address _delegationManager, + address _allocationManager ) ECDSAServiceManagerBase( _avsDirectory, _stakeRegistry, _rewardsCoordinator, - _delegationManager + _delegationManager, + _allocationManager ) {} diff --git a/test/mocks/RewardsCoordinatorMock.sol b/test/mocks/RewardsCoordinatorMock.sol index cc8404a0..db403ac6 100644 --- a/test/mocks/RewardsCoordinatorMock.sol +++ b/test/mocks/RewardsCoordinatorMock.sol @@ -129,5 +129,5 @@ contract RewardsCoordinatorMock is IRewardsCoordinator { address _rewardsUpdater, uint32 _activationDelay, uint16 _globalCommissionBips - ) external override {} + ) external {} } \ No newline at end of file diff --git a/test/unit/ECDSAServiceManager.t.sol b/test/unit/ECDSAServiceManager.t.sol index 1093b77a..a20c6d00 100644 --- a/test/unit/ECDSAServiceManager.t.sol +++ b/test/unit/ECDSAServiceManager.t.sol @@ -40,6 +40,8 @@ contract MockAVSDirectory { function updateAVSMetadataURI(string memory) external pure {} } +contract MockAllocationManager {} + contract MockRewardsCoordinator { function createAVSRewardsSubmission( IRewardsCoordinator.RewardsSubmission[] calldata @@ -49,6 +51,7 @@ contract MockRewardsCoordinator { contract ECDSAServiceManagerSetup is Test { MockDelegationManager public mockDelegationManager; MockAVSDirectory public mockAVSDirectory; + MockAllocationManager public mockAllocationManager; ECDSAStakeRegistryMock public mockStakeRegistry; MockRewardsCoordinator public mockRewardsCoordinator; ECDSAServiceManagerMock public serviceManager; @@ -60,6 +63,7 @@ contract ECDSAServiceManagerSetup is Test { function setUp() public { mockDelegationManager = new MockDelegationManager(); mockAVSDirectory = new MockAVSDirectory(); + mockAllocationManager = new MockAllocationManager(); mockStakeRegistry = new ECDSAStakeRegistryMock( IDelegationManager(address(mockDelegationManager)) ); @@ -69,7 +73,8 @@ contract ECDSAServiceManagerSetup is Test { address(mockAVSDirectory), address(mockStakeRegistry), address(mockRewardsCoordinator), - address(mockDelegationManager) + address(mockDelegationManager), + address(mockAllocationManager) ); operator1Pk = 1; diff --git a/test/unit/RegistryCoordinatorUnit.t.sol b/test/unit/RegistryCoordinatorUnit.t.sol index 6ae55d59..4129b8cb 100644 --- a/test/unit/RegistryCoordinatorUnit.t.sol +++ b/test/unit/RegistryCoordinatorUnit.t.sol @@ -260,7 +260,7 @@ contract RegistryCoordinatorUnitTests_RegisterOperator is RegistryCoordinatorUni registryCoordinator.pause(2 ** PAUSED_REGISTER_OPERATOR); cheats.startPrank(defaultOperator); - cheats.expectRevert(bytes("Pausable: index is paused")); + cheats.expectRevert(bytes4(keccak256("CurrentlyPaused()"))); registryCoordinator.registerOperator(emptyQuorumNumbers, defaultSocket, pubkeyRegistrationParams, emptySig); } @@ -591,7 +591,7 @@ contract RegistryCoordinatorUnitTests_DeregisterOperator_EjectOperator is Regist cheats.prank(pauser); registryCoordinator.pause(2 ** PAUSED_DEREGISTER_OPERATOR); - cheats.expectRevert(bytes("Pausable: index is paused")); + cheats.expectRevert(bytes4(keccak256("CurrentlyPaused()"))); cheats.prank(defaultOperator); registryCoordinator.deregisterOperator(quorumNumbers); } @@ -1526,7 +1526,7 @@ contract RegistryCoordinatorUnitTests_RegisterOperatorWithChurn is RegistryCoord hex"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B"; signatureWithSaltAndExpiry.salt = defaultSalt; cheats.prank(operatorToRegister); - cheats.expectRevert("ECDSA: invalid signature"); + cheats.expectRevert(bytes4(keccak256("InvalidSignature()"))); registryCoordinator.registerOperatorWithChurn( quorumNumbers, defaultSocket, @@ -1576,7 +1576,7 @@ contract RegistryCoordinatorUnitTests_UpdateOperators is RegistryCoordinatorUnit address[] memory operatorsToUpdate = new address[](1); operatorsToUpdate[0] = defaultOperator; - cheats.expectRevert(bytes("Pausable: index is paused")); + cheats.expectRevert(bytes4(keccak256("CurrentlyPaused()"))); registryCoordinator.updateOperators(operatorsToUpdate); } @@ -1657,7 +1657,7 @@ contract RegistryCoordinatorUnitTests_UpdateOperators is RegistryCoordinatorUnit bytes memory quorumNumbers = new bytes(1); quorumNumbers[0] = bytes1(defaultQuorumNumber); - cheats.expectRevert(bytes("Pausable: index is paused")); + cheats.expectRevert(bytes4(keccak256("CurrentlyPaused()"))); registryCoordinator.updateOperatorsForQuorum(operatorsToUpdate, quorumNumbers); } diff --git a/test/unit/ServiceManagerBase.t.sol b/test/unit/ServiceManagerBase.t.sol index 1d333814..609e8d2b 100644 --- a/test/unit/ServiceManagerBase.t.sol +++ b/test/unit/ServiceManagerBase.t.sol @@ -95,7 +95,7 @@ contract ServiceManagerBase_UnitTests is MockAVSDeployer, IServiceManagerBaseEve address(serviceManagerImplementation), address(proxyAdmin), abi.encodeWithSelector( - ServiceManagerMock.initialize.selector, msg.sender, msg.sender + ServiceManagerMock.initialize.selector, serviceManager.owner(), msg.sender, msg.sender ) ) ) diff --git a/test/unit/ServiceManagerMigration.t.sol b/test/unit/ServiceManagerMigration.t.sol index 67350529..5fd86846 100644 --- a/test/unit/ServiceManagerMigration.t.sol +++ b/test/unit/ServiceManagerMigration.t.sol @@ -99,7 +99,7 @@ contract ServiceManagerMigration_UnitTests is MockAVSDeployer, IServiceManagerBa address(serviceManagerImplementation), address(proxyAdmin), abi.encodeWithSelector( - ServiceManagerMock.initialize.selector, msg.sender, msg.sender + ServiceManagerMock.initialize.selector, serviceManager.owner(), msg.sender, msg.sender ) ) )