diff --git a/src/BLSApkRegistry.sol b/src/BLSApkRegistry.sol index ec445d3e..189716a6 100644 --- a/src/BLSApkRegistry.sol +++ b/src/BLSApkRegistry.sol @@ -79,7 +79,7 @@ contract BLSApkRegistry is BLSApkRegistryStorage { * @param quorumNumber The number of the new quorum */ function initializeQuorum(uint8 quorumNumber) public virtual onlyRegistryCoordinator { - require(apkHistory[quorumNumber].length == 0, "BLSApkRegistry.initializeQuorum: quorum already exists"); + require(apkHistory[quorumNumber].length == 0, QuorumAlreadyExists()); apkHistory[quorumNumber].push(ApkUpdate({ apkHash: bytes24(0), @@ -100,17 +100,9 @@ contract BLSApkRegistry is BLSApkRegistryStorage { BN254.G1Point calldata pubkeyRegistrationMessageHash ) external onlyRegistryCoordinator returns (bytes32 operatorId) { bytes32 pubkeyHash = BN254.hashG1Point(params.pubkeyG1); - require( - pubkeyHash != ZERO_PK_HASH, "BLSApkRegistry.registerBLSPublicKey: cannot register zero pubkey" - ); - require( - operatorToPubkeyHash[operator] == bytes32(0), - "BLSApkRegistry.registerBLSPublicKey: operator already registered pubkey" - ); - require( - pubkeyHashToOperator[pubkeyHash] == address(0), - "BLSApkRegistry.registerBLSPublicKey: public key already registered" - ); + require(pubkeyHash != ZERO_PK_HASH, ZeroPubKey()); + require(operatorToPubkeyHash[operator] == bytes32(0), OperatorAlreadyRegistered()); + require(pubkeyHashToOperator[pubkeyHash] == address(0), BLSPubkeyAlreadyRegistered()); // gamma = h(sigma, P, P', H(m)) uint256 gamma = uint256(keccak256(abi.encodePacked( @@ -130,7 +122,7 @@ contract BLSApkRegistry is BLSApkRegistryStorage { BN254.negGeneratorG2(), pubkeyRegistrationMessageHash.plus(BN254.generatorG1().scalar_mul(gamma)), params.pubkeyG2 - ), "BLSApkRegistry.registerBLSPublicKey: either the G1 signature is wrong, or G1 and G2 private key do not match"); + ), InvalidBLSSignatureOrPrivateKey()); operatorToPubkey[operator] = params.pubkeyG1; operatorToPubkeyHash[operator] = pubkeyHash; @@ -151,7 +143,7 @@ contract BLSApkRegistry is BLSApkRegistryStorage { // Validate quorum exists and get history length uint8 quorumNumber = uint8(quorumNumbers[i]); uint256 historyLength = apkHistory[quorumNumber].length; - require(historyLength != 0, "BLSApkRegistry._processQuorumApkUpdate: quorum does not exist"); + require(historyLength != 0, QuorumDoesNotExist()); // Update aggregate public key for this quorum newApk = currentApk[quorumNumber].plus(point); @@ -185,10 +177,7 @@ contract BLSApkRegistry is BLSApkRegistryStorage { BN254.G1Point memory pubkey = operatorToPubkey[operator]; bytes32 pubkeyHash = operatorToPubkeyHash[operator]; - require( - pubkeyHash != bytes32(0), - "BLSApkRegistry.getRegisteredPubkey: operator is not registered" - ); + require(pubkeyHash != bytes32(0), OperatorNotRegistered()); return (pubkey, pubkeyHash); } @@ -253,11 +242,11 @@ contract BLSApkRegistry is BLSApkRegistryStorage { */ require( blockNumber >= quorumApkUpdate.updateBlockNumber, - "BLSApkRegistry.getApkHashAtBlockNumberAndIndex: index too recent" + BlockNumberTooRecent() ); require( quorumApkUpdate.nextUpdateBlockNumber == 0 || blockNumber < quorumApkUpdate.nextUpdateBlockNumber, - "BLSApkRegistry.getApkHashAtBlockNumberAndIndex: not latest apk update" + BlockNumberNotLatest() ); return quorumApkUpdate.apkHash; @@ -280,9 +269,6 @@ contract BLSApkRegistry is BLSApkRegistryStorage { } function _checkRegistryCoordinator() internal view { - require( - msg.sender == address(registryCoordinator), - "BLSApkRegistry._checkRegistryCoordinator: caller is not the registry coordinator" - ); + require(msg.sender == address(registryCoordinator), OnlyRegistryCoordinatorOwner()); } } diff --git a/src/BLSSignatureChecker.sol b/src/BLSSignatureChecker.sol index 77d6fbe6..944ed4f7 100644 --- a/src/BLSSignatureChecker.sol +++ b/src/BLSSignatureChecker.sol @@ -31,10 +31,7 @@ contract BLSSignatureChecker is IBLSSignatureChecker { bool public staleStakesForbidden; modifier onlyCoordinatorOwner() { - require( - msg.sender == registryCoordinator.owner(), - "BLSSignatureChecker.onlyCoordinatorOwner: caller is not the owner of the registryCoordinator" - ); + require(msg.sender == registryCoordinator.owner(), OnlyRegistryCoordinatorOwner()); _; } @@ -91,29 +88,23 @@ contract BLSSignatureChecker is IBLSSignatureChecker { uint32 referenceBlockNumber, NonSignerStakesAndSignature memory params ) public view returns (QuorumStakeTotals memory, bytes32) { - require( - quorumNumbers.length != 0, - "BLSSignatureChecker.checkSignatures: empty quorum input" - ); + require(quorumNumbers.length != 0, InputEmptyQuorumNumbers()); require( (quorumNumbers.length == params.quorumApks.length) && (quorumNumbers.length == params.quorumApkIndices.length) && (quorumNumbers.length == params.totalStakeIndices.length) && (quorumNumbers.length == params.nonSignerStakeIndices.length), - "BLSSignatureChecker.checkSignatures: input quorum length mismatch" + InputArrayLengthMismatch() ); require( params.nonSignerPubkeys.length == params.nonSignerQuorumBitmapIndices.length, - "BLSSignatureChecker.checkSignatures: input nonsigner length mismatch" + InputNonSignerLengthMismatch() ); - require( - referenceBlockNumber < uint32(block.number), - "BLSSignatureChecker.checkSignatures: invalid reference block" - ); + require(referenceBlockNumber < uint32(block.number), InvalidReferenceBlocknumber()); // This method needs to calculate the aggregate pubkey for all signing operators across // all signing quorums. To do that, we can query the aggregate pubkey for each quorum @@ -155,7 +146,7 @@ contract BLSSignatureChecker is IBLSSignatureChecker { require( uint256(nonSigners.pubkeyHashes[j]) > uint256(nonSigners.pubkeyHashes[j - 1]), - "BLSSignatureChecker.checkSignatures: nonSignerPubkeys not sorted" + NonSignerPubkeysNotSorted() ); } @@ -207,7 +198,7 @@ contract BLSSignatureChecker is IBLSSignatureChecker { ) + withdrawalDelayBlocks > referenceBlockNumber, - "BLSSignatureChecker.checkSignatures: StakeRegistry updates must be within withdrawalDelayBlocks window" + StaleStakesForbidden() ); } @@ -220,7 +211,7 @@ contract BLSSignatureChecker is IBLSSignatureChecker { blockNumber: referenceBlockNumber, index: params.quorumApkIndices[i] }), - "BLSSignatureChecker.checkSignatures: quorumApk hash in storage does not match provided quorum apk" + InvalidQuorumApkHash() ); apk = apk.plus(params.quorumApks[i]); @@ -274,14 +265,8 @@ contract BLSSignatureChecker is IBLSSignatureChecker { params.apkG2, params.sigma ); - require( - pairingSuccessful, - "BLSSignatureChecker.checkSignatures: pairing precompile call failed" - ); - require( - signatureIsValid, - "BLSSignatureChecker.checkSignatures: signature is invalid" - ); + require(pairingSuccessful, InvalidBLSPairingKey()); + require(signatureIsValid, InvalidBLSSignature()); } // set signatoryRecordHash variable used for fraudproofs bytes32 signatoryRecordHash = keccak256( diff --git a/src/EjectionManager.sol b/src/EjectionManager.sol index 81860fc0..8ebf6002 100644 --- a/src/EjectionManager.sol +++ b/src/EjectionManager.sol @@ -67,7 +67,7 @@ contract EjectionManager is IEjectionManager, OwnableUpgradeable { * @dev The owner can eject operators without recording of stake ejection */ function ejectOperators(bytes32[][] memory _operatorIds) external { - require(isEjector[msg.sender] || msg.sender == owner(), "EjectionManager.ejectOperators: Only owner or ejector can eject"); + require(isEjector[msg.sender] || msg.sender == owner(), OnlyOwnerOrEjector()); for(uint i = 0; i < _operatorIds.length; ++i) { uint8 quorumNumber = uint8(i); @@ -137,7 +137,7 @@ contract EjectionManager is IEjectionManager, OwnableUpgradeable { ///@dev internal function to set the quorum ejection params function _setQuorumEjectionParams(uint8 _quorumNumber, QuorumEjectionParams memory _quorumEjectionParams) internal { - require(_quorumNumber < MAX_QUORUM_COUNT, "EjectionManager._setQuorumEjectionParams: Quorum number exceeds MAX_QUORUM_COUNT"); + require(_quorumNumber < MAX_QUORUM_COUNT, MaxQuorumCount()); quorumEjectionParams[_quorumNumber] = _quorumEjectionParams; emit QuorumEjectionParamsSet(_quorumNumber, _quorumEjectionParams.rateLimitWindow, _quorumEjectionParams.ejectableStakePercent); } diff --git a/src/IndexRegistry.sol b/src/IndexRegistry.sol index ce432d64..cab62a17 100644 --- a/src/IndexRegistry.sol +++ b/src/IndexRegistry.sol @@ -47,7 +47,7 @@ contract IndexRegistry is IndexRegistryStorage { // Validate quorum exists and get current operator count uint8 quorumNumber = uint8(quorumNumbers[i]); uint256 historyLength = _operatorCountHistory[quorumNumber].length; - require(historyLength != 0, "IndexRegistry.registerOperator: quorum does not exist"); + require(historyLength != 0, QuorumDoesNotExist()); /** * Increase the number of operators currently active for this quorum, @@ -87,7 +87,7 @@ contract IndexRegistry is IndexRegistryStorage { // Validate quorum exists and get the operatorIndex of the operator being deregistered uint8 quorumNumber = uint8(quorumNumbers[i]); uint256 historyLength = _operatorCountHistory[quorumNumber].length; - require(historyLength != 0, "IndexRegistry.registerOperator: quorum does not exist"); + require(historyLength != 0, QuorumDoesNotExist()); uint32 operatorIndexToRemove = currentOperatorIndex[quorumNumber][operatorId]; /** @@ -113,7 +113,7 @@ contract IndexRegistry is IndexRegistryStorage { * @param quorumNumber The number of the new quorum */ function initializeQuorum(uint8 quorumNumber) public virtual onlyRegistryCoordinator { - require(_operatorCountHistory[quorumNumber].length == 0, "IndexRegistry.createQuorum: quorum already exists"); + require(_operatorCountHistory[quorumNumber].length == 0, QuorumDoesNotExist()); _operatorCountHistory[quorumNumber].push(QuorumUpdate({ numOperators: 0, @@ -329,7 +329,7 @@ contract IndexRegistry is IndexRegistryStorage { operatorList[i] = _operatorIdForIndexAtBlockNumber(quorumNumber, uint32(i), blockNumber); require( operatorList[i] != OPERATOR_DOES_NOT_EXIST_ID, - "IndexRegistry.getOperatorListAtBlockNumber: operator does not exist at the given block number" + OperatorIdDoesNotExist() ); } return operatorList; @@ -342,6 +342,6 @@ contract IndexRegistry is IndexRegistryStorage { } function _checkRegistryCoordinator() internal view { - require(msg.sender == address(registryCoordinator), "IndexRegistry._checkRegistryCoordinator: caller is not the registry coordinator"); + require(msg.sender == address(registryCoordinator), OnlyRegistryCoordinator()); } } diff --git a/src/OperatorStateRetriever.sol b/src/OperatorStateRetriever.sol index 2af9e527..87672b66 100644 --- a/src/OperatorStateRetriever.sol +++ b/src/OperatorStateRetriever.sol @@ -26,6 +26,8 @@ contract OperatorStateRetriever { uint32[][] nonSignerStakeIndices; // nonSignerStakeIndices[quorumNumberIndex][nonSignerIndex] } + error OperatorNotRegistered(); + /** * @notice This function is intended to to be called by AVS operators every time a new task is created (i.e.) * the AVS coordinator makes a request to AVS operators. Since all of the crucial information is kept onchain, @@ -131,7 +133,7 @@ contract OperatorStateRetriever { checkSignaturesIndices.nonSignerQuorumBitmapIndices[i] ); - require(nonSignerQuorumBitmap != 0, "OperatorStateRetriever.getCheckSignaturesIndices: operator must be registered at blocknumber"); + require(nonSignerQuorumBitmap != 0, OperatorNotRegistered()); // if the operator was a part of the quorum and the quorum is a part of the provided quorumNumbers if ((nonSignerQuorumBitmap >> uint8(quorumNumbers[quorumNumberIndex])) & 1 == 1) { diff --git a/src/ServiceManagerBase.sol b/src/ServiceManagerBase.sol index 86c1e937..b7a07df8 100644 --- a/src/ServiceManagerBase.sol +++ b/src/ServiceManagerBase.sol @@ -30,10 +30,7 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage { /// @notice when applied to a function, only allows the RegistryCoordinator to call it modifier onlyRegistryCoordinator() { - require( - msg.sender == address(_registryCoordinator), - "ServiceManagerBase.onlyRegistryCoordinator: caller is not the registry coordinator" - ); + require(msg.sender == address(_registryCoordinator), OnlyRegistryCoordinator()); _; } @@ -209,7 +206,7 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage { function acceptProposedSlasher() external onlyOwner { require( block.timestamp >= slasherProposalTimestamp + SLASHER_PROPOSAL_DELAY, - "ServiceManager: Slasher proposal delay not met" + DelayPeriodNotPassed() ); _setSlasher(proposedSlasher); delete proposedSlasher; @@ -314,24 +311,14 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage { } function _checkRewardsInitiator() internal view { - require( - msg.sender == rewardsInitiator, - "ServiceManagerBase.onlyRewardsInitiator: caller is not the rewards initiator" - ); + require(msg.sender == rewardsInitiator, OnlyRewardsInitiator()); } function _checkStakeRegistry() internal view { - require( - msg.sender == address(_stakeRegistry), - "ServiceManagerBase.onlyStakeRegistry: caller is not the stake registry" - ); + require(msg.sender == address(_stakeRegistry), OnlyStakeRegistry()); } - function _checkSlasher() internal view { - require( - msg.sender == slasher, - "ServiceManagerBase.onlySlasher: caller is not the slasher" - ); + require(msg.sender == slasher, OnlySlasher()); } } diff --git a/src/StakeRegistry.sol b/src/StakeRegistry.sol index fe861b7b..3d2b5089 100644 --- a/src/StakeRegistry.sol +++ b/src/StakeRegistry.sol @@ -82,10 +82,7 @@ contract StakeRegistry is StakeRegistryStorage { // Retrieve the operator's current weighted stake for the quorum, reverting if they have not met // the minimum. (uint96 currentStake, bool hasMinimumStake) = _weightOfOperatorForQuorum(quorumNumber, operator); - require( - hasMinimumStake, - "StakeRegistry.registerOperator: Operator does not meet minimum stake requirement for quorum" - ); + require(hasMinimumStake, BelowMinimumStakeRequirement()); // Update the operator's stake int256 stakeDelta = _recordOperatorStakeUpdate({ @@ -197,7 +194,7 @@ contract StakeRegistry is StakeRegistryStorage { uint96 minimumStake, StrategyParams[] memory _strategyParams ) public virtual onlyRegistryCoordinator { - require(!_quorumExists(quorumNumber), "StakeRegistry.initializeQuorum: quorum already exists"); + require(!_quorumExists(quorumNumber), QuorumAlreadyExists()); _addStrategyParams(quorumNumber, _strategyParams); _setMinimumStakeForQuorum(quorumNumber, minimumStake); _setStakeType(quorumNumber, StakeType.TOTAL_DELEGATED); @@ -217,7 +214,7 @@ contract StakeRegistry is StakeRegistryStorage { uint32 lookAheadPeriod, StrategyParams[] memory _strategyParams ) public virtual onlyRegistryCoordinator { - require(!_quorumExists(quorumNumber), "StakeRegistry.initializeQuorum: quorum already exists"); + require(!_quorumExists(quorumNumber), QuorumAlreadyExists()); _addStrategyParams(quorumNumber, _strategyParams); _setMinimumStakeForQuorum(quorumNumber, minimumStake); _setStakeType(quorumNumber, StakeType.TOTAL_SLASHABLE); @@ -278,7 +275,7 @@ contract StakeRegistry is StakeRegistryStorage { uint256[] memory indicesToRemove ) public virtual onlyCoordinatorOwner quorumExists(quorumNumber) { uint256 toRemoveLength = indicesToRemove.length; - require(toRemoveLength > 0, "StakeRegistry.removeStrategies: no indices to remove provided"); + require(toRemoveLength > 0, InputArrayLengthZero()); StrategyParams[] storage _strategyParams = strategyParams[quorumNumber]; IStrategy[] storage _strategiesPerQuorum = strategiesPerQuorum[quorumNumber]; @@ -307,8 +304,8 @@ contract StakeRegistry is StakeRegistryStorage { uint96[] calldata newMultipliers ) public virtual onlyCoordinatorOwner quorumExists(quorumNumber) { uint256 numStrats = strategyIndices.length; - require(numStrats > 0, "StakeRegistry.modifyStrategyParams: no strategy indices provided"); - require(newMultipliers.length == numStrats, "StakeRegistry.modifyStrategyParams: input length mismatch"); + require(numStrats > 0, InputArrayLengthZero()); + require(newMultipliers.length == numStrats, InputArrayLengthMismatch()); StrategyParams[] storage _strategyParams = strategyParams[quorumNumber]; @@ -442,25 +439,22 @@ contract StakeRegistry is StakeRegistryStorage { uint8 quorumNumber, StrategyParams[] memory _strategyParams ) internal { - require(_strategyParams.length > 0, "StakeRegistry._addStrategyParams: no strategies provided"); + require(_strategyParams.length > 0, InputArrayLengthZero()); uint256 numStratsToAdd = _strategyParams.length; uint256 numStratsExisting = strategyParams[quorumNumber].length; require( numStratsExisting + numStratsToAdd <= MAX_WEIGHING_FUNCTION_LENGTH, - "StakeRegistry._addStrategyParams: exceed MAX_WEIGHING_FUNCTION_LENGTH" + InputArrayLengthMismatch() ); for (uint256 i = 0; i < numStratsToAdd; i++) { // fairly gas-expensive internal loop to make sure that the *same* strategy cannot be added multiple times for (uint256 j = 0; j < (numStratsExisting + i); j++) { require( strategyParams[quorumNumber][j].strategy != _strategyParams[i].strategy, - "StakeRegistry._addStrategyParams: cannot add same strategy 2x" + InputDuplicateStrategy() ); } - require( - _strategyParams[i].multiplier > 0, - "StakeRegistry._addStrategyParams: cannot add strategy with zero weight" - ); + require(_strategyParams[i].multiplier > 0, InputMultiplierZero()); strategyParams[quorumNumber].push(_strategyParams[i]); strategiesPerQuorum[quorumNumber].push(_strategyParams[i].strategy); emit StrategyAddedToQuorum(quorumNumber, _strategyParams[i].strategy); @@ -496,13 +490,10 @@ contract StakeRegistry is StakeRegistryStorage { * - blockNumber should be >= the update block number * - the next update block number should be either 0 or strictly greater than blockNumber */ - require( - blockNumber >= stakeUpdate.updateBlockNumber, - "StakeRegistry._validateStakeUpdateAtBlockNumber: stakeUpdate is from after blockNumber" - ); + require(blockNumber >= stakeUpdate.updateBlockNumber, InvalidBlockNumber()); require( stakeUpdate.nextUpdateBlockNumber == 0 || blockNumber < stakeUpdate.nextUpdateBlockNumber, - "StakeRegistry._validateStakeUpdateAtBlockNumber: there is a newer stakeUpdate available before blockNumber" + InvalidBlockNumber() ); } @@ -785,7 +776,7 @@ contract StakeRegistry is StakeRegistryStorage { _checkQuorumExists(quorumNumber); require( _totalStakeHistory[quorumNumber][0].updateBlockNumber <= blockNumber, - "StakeRegistry.getTotalStakeIndicesAtBlockNumber: quorum has no stake history at blockNumber" + EmptyStakeHistory() ); uint256 length = _totalStakeHistory[quorumNumber].length; for (uint256 j = 0; j < length; j++) { @@ -821,17 +812,14 @@ contract StakeRegistry is StakeRegistryStorage { function _checkRegistryCoordinator() internal view { - require( - msg.sender == address(registryCoordinator), - "StakeRegistry.onlyRegistryCoordinator: caller is not the RegistryCoordinator" - ); + require(msg.sender == address(registryCoordinator), OnlyRegistryCoordinator()); } function _checkRegistryCoordinatorOwner() internal view { - require(msg.sender == IRegistryCoordinator(registryCoordinator).owner(), "StakeRegistry.onlyCoordinatorOwner: caller is not the owner of the registryCoordinator"); + require(msg.sender == IRegistryCoordinator(registryCoordinator).owner(), OnlyRegistryCoordinatorOwner()); } function _checkQuorumExists(uint8 quorumNumber) internal view { - require(_quorumExists(quorumNumber), "StakeRegistry.quorumExists: quorum does not exist"); + require(_quorumExists(quorumNumber), QuorumDoesNotExist()); } } diff --git a/src/interfaces/IBLSApkRegistry.sol b/src/interfaces/IBLSApkRegistry.sol index ced99f6c..a93d4d53 100644 --- a/src/interfaces/IBLSApkRegistry.sol +++ b/src/interfaces/IBLSApkRegistry.sol @@ -5,11 +5,34 @@ import {IRegistry} from "./IRegistry.sol"; import {BN254} from "../libraries/BN254.sol"; +interface IBLSApkRegistryErrors { + /// @dev Thrown when the caller is not the owner of the registry coordinator. + error OnlyRegistryCoordinatorOwner(); + /// @dev Thrown when a quorum being created already exists. + error QuorumAlreadyExists(); + /// @dev Thrown when a quorum does not exist. + error QuorumDoesNotExist(); + /// @dev Thrown when a BLS pubkey provided is zero pubkey + error ZeroPubKey(); + /// @dev Thrown when an operator has already registered a BLS pubkey. + error OperatorAlreadyRegistered(); + /// @dev Thrown when the operator is not registered. + error OperatorNotRegistered(); + /// @dev Thrown when a BLS pubkey has already been registered for an operator. + error BLSPubkeyAlreadyRegistered(); + /// @dev Thrown when either the G1 signature is wrong, or G1 and G2 private key do not match. + error InvalidBLSSignatureOrPrivateKey(); + /// @dev Thrown when the quorum apk update block number is too recent. + error BlockNumberTooRecent(); + /// @dev Thrown when blocknumber and index provided is not the latest apk update. + error BlockNumberNotLatest(); +} + /** * @title Minimal interface for a registry that keeps track of aggregate operator public keys across many quorums. * @author Layr Labs, Inc. */ -interface IBLSApkRegistry is IRegistry { +interface IBLSApkRegistry is IRegistry, IBLSApkRegistryErrors { // STRUCTS /// @notice Data structure used to track the history of the Aggregate Public Key of all operators struct ApkUpdate { diff --git a/src/interfaces/IBLSSignatureChecker.sol b/src/interfaces/IBLSSignatureChecker.sol index aa92e56f..4ab73f4c 100644 --- a/src/interfaces/IBLSSignatureChecker.sol +++ b/src/interfaces/IBLSSignatureChecker.sol @@ -7,13 +7,36 @@ import {IStakeRegistry, IDelegationManager} from "./IStakeRegistry.sol"; import {BN254} from "../libraries/BN254.sol"; +interface IBLSSignatureCheckerErrors { + /// @dev Thrown when the caller is not the registry coordinator owner. + error OnlyRegistryCoordinatorOwner(); + /// @dev Thrown when the quorum numbers input in is empty. + error InputEmptyQuorumNumbers(); + /// @dev Thrown when two array parameters have mismatching lengths. + error InputArrayLengthMismatch(); + /// @dev Thrown when the non-signer pubkey length does not match non-signer bitmap indices length. + error InputNonSignerLengthMismatch(); + /// @dev Thrown when the reference block number is invalid. + error InvalidReferenceBlocknumber(); + /// @dev Thrown when the non signer pubkeys are not sorted. + error NonSignerPubkeysNotSorted(); + /// @dev Thrown when StakeRegistry updates have not been updated within withdrawalDelayBlocks window + error StaleStakesForbidden(); + /// @dev Thrown when the quorum apk hash in storage does not match provided quorum apk. + error InvalidQuorumApkHash(); + /// @dev Thrown when BLS pairing precompile call fails. + error InvalidBLSPairingKey(); + /// @dev Thrown when BLS signature is invalid. + error InvalidBLSSignature(); +} + /** * @title Used for checking BLS aggregate signatures from the operators of a EigenLayer AVS with the RegistryCoordinator/BLSApkRegistry/StakeRegistry architechture. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service * @notice This is the contract for checking the validity of aggregate operator signatures. */ -interface IBLSSignatureChecker { +interface IBLSSignatureChecker is IBLSSignatureCheckerErrors { // DATA STRUCTURES struct NonSignerStakesAndSignature { diff --git a/src/interfaces/IEjectionManager.sol b/src/interfaces/IEjectionManager.sol index 545e0a7c..478e21d8 100644 --- a/src/interfaces/IEjectionManager.sol +++ b/src/interfaces/IEjectionManager.sol @@ -1,11 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; +interface IEjectionManagerErrors { + /// @dev Thrown when the caller is not the owner or ejector. + error OnlyOwnerOrEjector(); + /// @dev Thrown when quorum number exceeds MAX_QUORUM_COUNT. + error MaxQuorumCount(); +} + /** * @title Interface for a contract that ejects operators from an AVSs RegistryCoordinator * @author Layr Labs, Inc. */ -interface IEjectionManager { +interface IEjectionManager is IEjectionManagerErrors { /// @notice A quorum's ratelimit parameters struct QuorumEjectionParams { diff --git a/src/interfaces/IIndexRegistry.sol b/src/interfaces/IIndexRegistry.sol index 579fb23b..df1e0e73 100644 --- a/src/interfaces/IIndexRegistry.sol +++ b/src/interfaces/IIndexRegistry.sol @@ -3,11 +3,20 @@ pragma solidity ^0.8.27; import {IRegistry} from "./IRegistry.sol"; +interface IIndexRegistryErrors { + /// @dev Thrown when a function is called by an address that is not the RegistryCoordinator + error OnlyRegistryCoordinator(); + /// @dev Thrown when a quorum has 0 length history and thus does not exist + error QuorumDoesNotExist(); + /// @dev Thrown when an operatorId is not found in the registry at a given block number + error OperatorIdDoesNotExist(); +} + /** * @title Interface for a `Registry`-type contract that keeps track of an ordered list of operators for up to 256 quorums. * @author Layr Labs, Inc. */ -interface IIndexRegistry is IRegistry { +interface IIndexRegistry is IRegistry, IIndexRegistryErrors { // EVENTS // emitted when an operator's index in the ordered operator list for the quorum with number `quorumNumber` is updated diff --git a/src/interfaces/IServiceManager.sol b/src/interfaces/IServiceManager.sol index 133c3789..ccc0603f 100644 --- a/src/interfaces/IServiceManager.sol +++ b/src/interfaces/IServiceManager.sol @@ -9,12 +9,24 @@ import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/ import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; import {IAVSRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IAVSRegistrar.sol"; +interface IServiceManagerErrors { + /// @dev Thrown when a function is called by an address that is not the RegistryCoordinator + error OnlyRegistryCoordinator(); + /// @dev Thrown when a function is called by an address that is not the RewardsInitiator + error OnlyRewardsInitiator(); + /// @dev Thrown when a function is called by an address that is not the Slasher + error OnlyStakeRegistry(); + /// @dev Thrown when a function is called by an address that is not the Slasher + error OnlySlasher(); + /// @dev Thrown when a slashing proposal delay has not been met yet. + error DelayPeriodNotPassed(); +} /** * @title Minimal interface for a ServiceManager-type contract that forms the single point for an AVS to push updates to EigenLayer * @author Layr Labs, Inc. */ -interface IServiceManager is IServiceManagerUI { +interface IServiceManager is IServiceManagerUI, IServiceManagerErrors { /** * @notice Creates a new rewards submission to the EigenLayer RewardsCoordinator contract, to be split amongst the * set of stakers delegated to operators who are registered to this `avs` diff --git a/src/interfaces/ISlasher.sol b/src/interfaces/ISlasher.sol index a150bc94..44222150 100644 --- a/src/interfaces/ISlasher.sol +++ b/src/interfaces/ISlasher.sol @@ -25,6 +25,21 @@ interface ISlasherEvents { ); } +interface ISlasherErrors { + /// @dev Thrown when the caller is not the veto committee + error OnlyVetoCommittee(); + /// @dev Thrown when the caller is not the slasher + error OnlySlasher(); + /// @dev Thrown when the veto period has passed + error VetoPeriodPassed(); + /// @dev Thrown when the veto period has not passed + error VetoPeriodNotPassed(); + /// @dev Thrown when the slashing request is cancelled + error SlashingRequestIsCancelled(); + /// @dev Thrown when the slashing request was not already requested + error SlashingRequestNotRequested(); +} + interface ISlasherTypes { enum SlashingStatus { Null, @@ -41,4 +56,4 @@ interface ISlasherTypes { } -interface ISlasher is ISlasherEvents, ISlasherTypes{} +interface ISlasher is ISlasherEvents, ISlasherTypes, ISlasherErrors {} diff --git a/src/interfaces/IStakeRegistry.sol b/src/interfaces/IStakeRegistry.sol index 3b82fefb..d56c01c1 100644 --- a/src/interfaces/IStakeRegistry.sol +++ b/src/interfaces/IStakeRegistry.sol @@ -11,11 +11,37 @@ enum StakeType { TOTAL_SLASHABLE } +interface IStakeRegistryErrors { + /// @dev Thrown when the caller is not the registry coordinator + error OnlyRegistryCoordinator(); + /// @dev Thrown when the caller is not the owner of the registry coordinator + error OnlyRegistryCoordinatorOwner(); + /// @dev Thrown when the stake is below the minimum required for a quorum + error BelowMinimumStakeRequirement(); + /// @dev Thrown when a quorum being created already exists. + error QuorumAlreadyExists(); + /// @dev Thrown when a quorum does not exist. + error QuorumDoesNotExist(); + /// @dev Thrown when two array parameters have mismatching lengths. + error InputArrayLengthMismatch(); + /// @dev Thrown when input arrays length is zero. + error InputArrayLengthZero(); + /// @dev Thrown when a duplicate strategy is provided in input array. + error InputDuplicateStrategy(); + /// @dev Thrown when multiplier input is zero. + error InputMultiplierZero(); + /// @dev Thrown when the blocknumber provided is not >= the provided StakeUpdate's updateBlockNumber + /// or if the blocknumber provided is not the nextUpdateBlockNumber + error InvalidBlockNumber(); + /// @dev Thrown when the quorum has no stake history at block number provided. + error EmptyStakeHistory(); +} + /** * @title Interface for a `Registry` that keeps track of stakes of operators for up to 256 quorums. * @author Layr Labs, Inc. */ -interface IStakeRegistry is IRegistry { +interface IStakeRegistry is IRegistry, IStakeRegistryErrors { // DATA STRUCTURES /// @notice struct used to store the stakes of an individual operator or the sum of all operators' stakes, for storage diff --git a/src/libraries/BN254.sol b/src/libraries/BN254.sol index 61a20929..dcda7a31 100644 --- a/src/libraries/BN254.sol +++ b/src/libraries/BN254.sol @@ -46,6 +46,17 @@ library BN254 { uint256[2] Y; } + /// @dev Thrown when the sum of two points of G1 fails + error ECAddFailed(); + /// @dev Thrown when the scalar multiplication of a point of G1 fails + error ECMulFailed(); + /// @dev Thrown when the scalar is too large. + error ScalarTooLarge(); + /// @dev Thrown when the pairing check fails + error ECPairingFailed(); + /// @dev Thrown when the exponentiation mod fails + error ExpModFailed(); + function generatorG1() internal pure returns (G1Point memory) { return G1Point(1, 2); } @@ -114,7 +125,7 @@ library BN254 { } } - require(success, "ec-add-failed"); + require(success, ECAddFailed()); } /** @@ -124,7 +135,7 @@ library BN254 { * @dev this function is only safe to use if the scalar is 9 bits or less */ function scalar_mul_tiny(BN254.G1Point memory p, uint16 s) internal view returns (BN254.G1Point memory) { - require(s < 2**9, "scalar-too-large"); + require(s < 2**9, ScalarTooLarge()); // if s is 1 return p if(s == 1) { @@ -180,7 +191,7 @@ library BN254 { invalid() } } - require(success, "ec-mul-failed"); + require(success, ECMulFailed()); } /** @@ -223,7 +234,7 @@ library BN254 { } } - require(success, "pairing-opcode-failed"); + require(success, ECPairingFailed()); return out[0] != 0; } @@ -344,7 +355,7 @@ library BN254 { invalid() } } - require(success, "BN254.expMod: call failure"); + require(success, ExpModFailed()); return output[0]; } } diff --git a/src/libraries/BitmapUtils.sol b/src/libraries/BitmapUtils.sol index 9c53aadd..3930209a 100644 --- a/src/libraries/BitmapUtils.sol +++ b/src/libraries/BitmapUtils.sol @@ -7,6 +7,13 @@ pragma solidity ^0.8.27; * @author Layr Labs, Inc. */ library BitmapUtils { + /// @dev Thrown when the input byte array is too long to be converted to a bitmap + error BytesArrayLengthTooLong(); + /// @dev Thrown when the input byte array is not strictly ordered + error BytesArrayNotOrdered(); + /// @dev Thrown when the bitmap value is too large + error BitmapValueTooLarge(); + /** * @notice Byte arrays are meant to contain unique bytes. * If the array length exceeds 256, then it's impossible for all entries to be unique. @@ -24,8 +31,7 @@ library BitmapUtils { */ function orderedBytesArrayToBitmap(bytes memory orderedBytesArray) internal pure returns (uint256) { // sanity-check on input. a too-long input would fail later on due to having duplicate entry(s) - require(orderedBytesArray.length <= MAX_BYTE_ARRAY_LENGTH, - "BitmapUtils.orderedBytesArrayToBitmap: orderedBytesArray is too long"); + require(orderedBytesArray.length <= MAX_BYTE_ARRAY_LENGTH, BytesArrayLengthTooLong()); // return empty bitmap early if length of array is 0 if (orderedBytesArray.length == 0) { @@ -46,7 +52,7 @@ library BitmapUtils { // construct a single-bit mask from the numerical value of the next byte of the array bitMask = uint256(1 << uint8(orderedBytesArray[i])); // check strictly ascending array ordering by comparing the mask to the bitmap so far (revert if mask isn't greater than bitmap) - require(bitMask > bitmap, "BitmapUtils.orderedBytesArrayToBitmap: orderedBytesArray is not ordered"); + require(bitMask > bitmap, BytesArrayNotOrdered()); // add the entry to the bitmap bitmap = (bitmap | bitMask); } @@ -62,9 +68,7 @@ library BitmapUtils { function orderedBytesArrayToBitmap(bytes memory orderedBytesArray, uint8 bitUpperBound) internal pure returns (uint256) { uint256 bitmap = orderedBytesArrayToBitmap(orderedBytesArray); - require((1 << bitUpperBound) > bitmap, - "BitmapUtils.orderedBytesArrayToBitmap: bitmap exceeds max value" - ); + require((1 << bitUpperBound) > bitmap, BitmapValueTooLarge()); return bitmap; } diff --git a/src/libraries/QuorumBitmapHistoryLib.sol b/src/libraries/QuorumBitmapHistoryLib.sol index 72cbf114..50f6880b 100644 --- a/src/libraries/QuorumBitmapHistoryLib.sol +++ b/src/libraries/QuorumBitmapHistoryLib.sol @@ -6,6 +6,12 @@ import {IRegistryCoordinator} from "../interfaces/IRegistryCoordinator.sol"; /// @title QuorumBitmapHistoryLib /// @notice This library operates on the _operatorBitmapHistory in the RegistryCoordinator library QuorumBitmapHistoryLib { + /// @dev Thrown when the quorum bitmap update is not found + error BitmapUpdateNotFound(); + /// @dev Thrown when quorum bitmap update is after the block number + error BitmapUpdateIsAfterBlockNumber(); + /// @dev Thrown when the next update block number is not 0 and strictly greater than blockNumber + error NextBitmapUpdateIsBeforeBlockNumber(); /// @notice Retrieves the index of the quorum bitmap update at or before the specified block number /// @param self The mapping of operator IDs to their quorum bitmap update history @@ -88,12 +94,12 @@ library QuorumBitmapHistoryLib { */ require( blockNumber >= quorumBitmapUpdate.updateBlockNumber, - "RegistryCoordinator.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from after blockNumber" + BitmapUpdateIsAfterBlockNumber() ); require( quorumBitmapUpdate.nextUpdateBlockNumber == 0 || blockNumber < quorumBitmapUpdate.nextUpdateBlockNumber, - "RegistryCoordinator.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from before blockNumber" + NextBitmapUpdateIsBeforeBlockNumber() ); return quorumBitmapUpdate.quorumBitmap; diff --git a/src/slashers/VetoableSlasher.sol b/src/slashers/VetoableSlasher.sol index 0f9c623f..880b481f 100644 --- a/src/slashers/VetoableSlasher.sol +++ b/src/slashers/VetoableSlasher.sol @@ -32,20 +32,17 @@ contract VetoableSlashing is SlasherBase { function cancelSlashingRequest(uint256 requestId) external virtual onlyVetoCommittee { require( block.timestamp < slashingRequests[requestId].requestTimestamp + VETO_PERIOD, - "VetoableSlashing.cancelSlashingRequest: veto period has passed" + VetoPeriodPassed() ); - require(slashingRequests[requestId].status == SlashingStatus.Requested, "VetoableSlashing.cancelSlashingRequest: request is not in Requested status"); + require(slashingRequests[requestId].status == SlashingStatus.Requested, SlashingRequestNotRequested()); _cancelSlashingRequest(requestId); } function fulfillSlashingRequest(uint256 requestId) external virtual onlySlasher { SlashingRequest storage request = slashingRequests[requestId]; - require( - block.timestamp >= request.requestTimestamp + VETO_PERIOD, - "VetoableSlashing.fulfillSlashingRequest: veto period has not passed" - ); - require(request.status == SlashingStatus.Requested, "VetoableSlashing.fulfillSlashingRequest: request has been cancelled"); + require(block.timestamp >= request.requestTimestamp + VETO_PERIOD, VetoPeriodNotPassed()); + require(request.status == SlashingStatus.Requested, SlashingRequestIsCancelled()); request.status = SlashingStatus.Completed; @@ -72,6 +69,6 @@ contract VetoableSlashing is SlasherBase { } function _checkVetoCommittee(address account) internal view virtual { - require(account == vetoCommittee, "VetoableSlashing._checkVetoCommittee: caller is not the veto committee"); + require(account == vetoCommittee, OnlyVetoCommittee()); } } diff --git a/src/slashers/base/SlasherBase.sol b/src/slashers/base/SlasherBase.sol index 283a764c..f1d46870 100644 --- a/src/slashers/base/SlasherBase.sol +++ b/src/slashers/base/SlasherBase.sol @@ -28,7 +28,7 @@ abstract contract SlasherBase is Initializable, SlasherStorage { } function _checkSlasher(address account) internal view virtual { - require(account == slasher, "SlasherBase._checkSlasher: caller is not the slasher"); + require(account == slasher, OnlySlasher()); } } diff --git a/src/unaudited/ECDSAServiceManagerBase.sol b/src/unaudited/ECDSAServiceManagerBase.sol index 805a961a..e9fd55a3 100644 --- a/src/unaudited/ECDSAServiceManagerBase.sol +++ b/src/unaudited/ECDSAServiceManagerBase.sol @@ -44,10 +44,7 @@ abstract contract ECDSAServiceManagerBase is * This is used to restrict certain registration and deregistration functionality to the `stakeRegistry` */ modifier onlyStakeRegistry() { - require( - msg.sender == stakeRegistry, - "ECDSAServiceManagerBase.onlyStakeRegistry: caller is not the stakeRegistry" - ); + require(msg.sender == stakeRegistry, OnlyStakeRegistry()); _; } @@ -60,10 +57,7 @@ abstract contract ECDSAServiceManagerBase is } function _checkRewardsInitiator() internal view { - require( - msg.sender == rewardsInitiator, - "ECDSAServiceManagerBase.onlyRewardsInitiator: caller is not the rewards initiator" - ); + require(msg.sender == rewardsInitiator, OnlyRewardsInitiator()); } /** diff --git a/test/unit/BLSApkRegistryUnit.t.sol b/test/unit/BLSApkRegistryUnit.t.sol index aacfe9d8..fa644cae 100644 --- a/test/unit/BLSApkRegistryUnit.t.sol +++ b/test/unit/BLSApkRegistryUnit.t.sol @@ -8,6 +8,7 @@ import "../harnesses/BitmapUtilsWrapper.sol"; import "../utils/BLSMockAVSDeployer.sol"; import {IBLSApkRegistryEvents} from "../events/IBLSApkRegistryEvents.sol"; +import {IBLSApkRegistryErrors} from "../../src/interfaces/IBLSApkRegistry.sol"; contract BLSApkRegistryUnitTests is BLSMockAVSDeployer, IBLSApkRegistryEvents { using BitmapUtils for uint192; @@ -309,9 +310,7 @@ contract BLSApkRegistryUnitTests_configAndGetters is BLSApkRegistryUnitTests { cheats.assume(nonCoordinatorAddress != address(registryCoordinator)); cheats.prank(address(nonCoordinatorAddress)); - cheats.expectRevert( - "BLSApkRegistry._checkRegistryCoordinator: caller is not the registry coordinator" - ); + cheats.expectRevert(IBLSApkRegistryErrors.OnlyRegistryCoordinatorOwner.selector); blsApkRegistry.initializeQuorum(defaultQuorumNumber); } } @@ -334,9 +333,7 @@ contract BLSApkRegistryUnitTests_registerBLSPublicKey is .pubkeyRegistrationMessageHash(defaultOperator); cheats.prank(address(nonCoordinatorAddress)); - cheats.expectRevert( - "BLSApkRegistry._checkRegistryCoordinator: caller is not the registry coordinator" - ); + cheats.expectRevert(IBLSApkRegistryErrors.OnlyRegistryCoordinatorOwner.selector); blsApkRegistry.registerBLSPublicKey( defaultOperator, pubkeyRegistrationParams, @@ -353,9 +350,7 @@ contract BLSApkRegistryUnitTests_registerBLSPublicKey is .pubkeyRegistrationMessageHash(operator); cheats.prank(address(registryCoordinator)); - cheats.expectRevert( - "BLSApkRegistry.registerBLSPublicKey: cannot register zero pubkey" - ); + cheats.expectRevert(IBLSApkRegistryErrors.ZeroPubKey.selector); blsApkRegistry.registerBLSPublicKey( operator, pubkeyRegistrationParams, @@ -379,9 +374,7 @@ contract BLSApkRegistryUnitTests_registerBLSPublicKey is messageHash ); - cheats.expectRevert( - "BLSApkRegistry.registerBLSPublicKey: operator already registered pubkey" - ); + cheats.expectRevert(IBLSApkRegistryErrors.OperatorAlreadyRegistered.selector); blsApkRegistry.registerBLSPublicKey( operator, pubkeyRegistrationParams, @@ -412,9 +405,7 @@ contract BLSApkRegistryUnitTests_registerBLSPublicKey is messageHash ); - cheats.expectRevert( - "BLSApkRegistry.registerBLSPublicKey: public key already registered" - ); + cheats.expectRevert(IBLSApkRegistryErrors.BLSPubkeyAlreadyRegistered.selector); blsApkRegistry.registerBLSPublicKey( operator2, pubkeyRegistrationParams, @@ -442,9 +433,7 @@ contract BLSApkRegistryUnitTests_registerBLSPublicKey is pubkeyRegistrationParams.pubkeyRegistrationSignature = invalidSignature; cheats.startPrank(address(registryCoordinator)); - cheats.expectRevert( - "BLSApkRegistry.registerBLSPublicKey: either the G1 signature is wrong, or G1 and G2 private key do not match" - ); + cheats.expectRevert(IBLSApkRegistryErrors.InvalidBLSSignatureOrPrivateKey.selector); blsApkRegistry.registerBLSPublicKey( operator, pubkeyRegistrationParams, @@ -468,9 +457,7 @@ contract BLSApkRegistryUnitTests_registerBLSPublicKey is BN254.G1Point memory messageHash = registryCoordinator .pubkeyRegistrationMessageHash(operator); cheats.prank(address(registryCoordinator)); - cheats.expectRevert( - "BLSApkRegistry.registerBLSPublicKey: either the G1 signature is wrong, or G1 and G2 private key do not match" - ); + cheats.expectRevert(IBLSApkRegistryErrors.InvalidBLSSignatureOrPrivateKey.selector); blsApkRegistry.registerBLSPublicKey( operator, pubkeyRegistrationParams, @@ -544,9 +531,7 @@ contract BLSApkRegistryUnitTests_registerOperator is BLSApkRegistryUnitTests { cheats.assume(nonCoordinatorAddress != address(registryCoordinator)); cheats.prank(nonCoordinatorAddress); - cheats.expectRevert( - "BLSApkRegistry._checkRegistryCoordinator: caller is not the registry coordinator" - ); + cheats.expectRevert(IBLSApkRegistryErrors.OnlyRegistryCoordinatorOwner.selector); blsApkRegistry.registerOperator(nonCoordinatorAddress, new bytes(0)); } @@ -554,9 +539,7 @@ contract BLSApkRegistryUnitTests_registerOperator is BLSApkRegistryUnitTests { address operator ) public filterFuzzedAddressInputs(operator) { cheats.prank(address(registryCoordinator)); - cheats.expectRevert( - "BLSApkRegistry.getRegisteredPubkey: operator is not registered" - ); + cheats.expectRevert(IBLSApkRegistryErrors.OperatorNotRegistered.selector); blsApkRegistry.registerOperator(operator, new bytes(1)); } @@ -577,9 +560,7 @@ contract BLSApkRegistryUnitTests_registerOperator is BLSApkRegistryUnitTests { _registerDefaultBLSPubkey(operator); cheats.prank(address(registryCoordinator)); - cheats.expectRevert( - "BLSApkRegistry._processQuorumApkUpdate: quorum does not exist" - ); + cheats.expectRevert(IBLSApkRegistryErrors.QuorumDoesNotExist.selector); blsApkRegistry.registerOperator(operator, quorumNumbers); } @@ -672,9 +653,7 @@ contract BLSApkRegistryUnitTests_deregisterOperator is BLSApkRegistryUnitTests { cheats.assume(nonCoordinatorAddress != address(registryCoordinator)); cheats.prank(nonCoordinatorAddress); - cheats.expectRevert( - "BLSApkRegistry._checkRegistryCoordinator: caller is not the registry coordinator" - ); + cheats.expectRevert(IBLSApkRegistryErrors.OnlyRegistryCoordinatorOwner.selector); blsApkRegistry.deregisterOperator(nonCoordinatorAddress, new bytes(0)); } @@ -682,9 +661,7 @@ contract BLSApkRegistryUnitTests_deregisterOperator is BLSApkRegistryUnitTests { address operator ) public filterFuzzedAddressInputs(operator) { cheats.prank(address(registryCoordinator)); - cheats.expectRevert( - "BLSApkRegistry.getRegisteredPubkey: operator is not registered" - ); + cheats.expectRevert(IBLSApkRegistryErrors.OperatorNotRegistered.selector); blsApkRegistry.registerOperator(operator, new bytes(1)); } @@ -708,9 +685,7 @@ contract BLSApkRegistryUnitTests_deregisterOperator is BLSApkRegistryUnitTests { _registerOperator(operator, validQuorumNumbers); cheats.prank(address(registryCoordinator)); - cheats.expectRevert( - "BLSApkRegistry._processQuorumApkUpdate: quorum does not exist" - ); + cheats.expectRevert(IBLSApkRegistryErrors.QuorumDoesNotExist.selector); blsApkRegistry.deregisterOperator(operator, invalidQuorumNumbers); } @@ -1080,9 +1055,7 @@ contract BLSApkRegistryUnitTests_quorumApkUpdates is BLSApkRegistryUnitTests { } if (wrongBlockNumber < startingBlockNumber + indexToCheck * 100) { emit log_named_uint("index too recent: ", indexToCheck); - cheats.expectRevert( - "BLSApkRegistry.getApkHashAtBlockNumberAndIndex: index too recent" - ); + cheats.expectRevert(IBLSApkRegistryErrors.BlockNumberTooRecent.selector); blsApkRegistry.getApkHashAtBlockNumberAndIndex( defaultQuorumNumber, wrongBlockNumber, @@ -1093,9 +1066,7 @@ contract BLSApkRegistryUnitTests_quorumApkUpdates is BLSApkRegistryUnitTests { wrongBlockNumber >= startingBlockNumber + (indexToCheck + 1) * 100 ) { emit log_named_uint("index not latest: ", indexToCheck); - cheats.expectRevert( - "BLSApkRegistry.getApkHashAtBlockNumberAndIndex: not latest apk update" - ); + cheats.expectRevert(IBLSApkRegistryErrors.BlockNumberNotLatest.selector); blsApkRegistry.getApkHashAtBlockNumberAndIndex( defaultQuorumNumber, wrongBlockNumber, diff --git a/test/unit/BLSSignatureCheckerUnit.t.sol b/test/unit/BLSSignatureCheckerUnit.t.sol index 74b8f1da..d1d0ac7f 100644 --- a/test/unit/BLSSignatureCheckerUnit.t.sol +++ b/test/unit/BLSSignatureCheckerUnit.t.sol @@ -3,6 +3,10 @@ pragma solidity ^0.8.27; import "../../src/BLSSignatureChecker.sol"; import "../utils/BLSMockAVSDeployer.sol"; +import {IBLSSignatureCheckerErrors} from "../../src/interfaces/IBLSSignatureChecker.sol"; +import {IBLSApkRegistryErrors} from "../../src/interfaces/IBLSApkRegistry.sol"; +import {QuorumBitmapHistoryLib} from "../../src/libraries/QuorumBitmapHistoryLib.sol"; +import {IStakeRegistryErrors} from "../../src/interfaces/IStakeRegistry.sol"; contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { using BN254 for BN254.G1Point; @@ -18,7 +22,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { } function test_setStaleStakesForbidden_revert_notRegCoordOwner() public { - cheats.expectRevert("BLSSignatureChecker.onlyCoordinatorOwner: caller is not the owner of the registryCoordinator"); + cheats.expectRevert(IBLSSignatureCheckerErrors.OnlyRegistryCoordinatorOwner.selector); blsSignatureChecker.setStaleStakesForbidden(true); } @@ -166,7 +170,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // make one part of the input incorrect length incorrectLengthInputs.quorumApks = new BN254.G1Point[](5); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: input quorum length mismatch"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InputArrayLengthMismatch.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -178,7 +182,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { incorrectLengthInputs.quorumApks = nonSignerStakesAndSignature.quorumApks; // make one part of the input incorrect length incorrectLengthInputs.quorumApkIndices = new uint32[](5); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: input quorum length mismatch"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InputArrayLengthMismatch.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -190,7 +194,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { incorrectLengthInputs.quorumApkIndices = nonSignerStakesAndSignature.quorumApkIndices; // make one part of the input incorrect length incorrectLengthInputs.totalStakeIndices = new uint32[](5); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: input quorum length mismatch"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InputArrayLengthMismatch.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -202,7 +206,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { incorrectLengthInputs.totalStakeIndices = nonSignerStakesAndSignature.totalStakeIndices; // make one part of the input incorrect length incorrectLengthInputs.nonSignerStakeIndices = new uint32[][](5); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: input quorum length mismatch"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InputArrayLengthMismatch.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -214,7 +218,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { incorrectLengthInputs.nonSignerStakeIndices = nonSignerStakesAndSignature.nonSignerStakeIndices; // make one part of the input incorrect length incorrectLengthInputs.nonSignerQuorumBitmapIndices = new uint32[](nonSignerStakesAndSignature.nonSignerPubkeys.length + 1); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: input nonsigner length mismatch"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InputNonSignerLengthMismatch.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -243,7 +247,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // Create an invalid reference block: any block number >= the current block uint32 invalidReferenceBlock = uint32(block.number + (pseudoRandomNumber % 20)); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: invalid reference block"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InvalidReferenceBlocknumber.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -263,7 +267,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // swap out a pubkey to make sure there is a duplicate nonSignerStakesAndSignature.nonSignerPubkeys[1] = nonSignerStakesAndSignature.nonSignerPubkeys[0]; - cheats.expectRevert("BLSSignatureChecker.checkSignatures: nonSignerPubkeys not sorted"); + cheats.expectRevert(IBLSSignatureCheckerErrors.NonSignerPubkeysNotSorted.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -284,7 +288,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // swap two pubkeys to ensure ordering is wrong (nonSignerStakesAndSignature.nonSignerPubkeys[0], nonSignerStakesAndSignature.nonSignerPubkeys[1]) = (nonSignerStakesAndSignature.nonSignerPubkeys[1], nonSignerStakesAndSignature.nonSignerPubkeys[0]); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: nonSignerPubkeys not sorted"); + cheats.expectRevert(IBLSSignatureCheckerErrors.NonSignerPubkeysNotSorted.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -330,7 +334,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { referenceBlockNumber += 1; // roll forward to reference + 1 to ensure the referenceBlockNumber is still valid cheats.roll(referenceBlockNumber + 1); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: StakeRegistry updates must be within withdrawalDelayBlocks window"); + cheats.expectRevert(IBLSSignatureCheckerErrors.StaleStakesForbidden.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -353,7 +357,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // set the nonSignerQuorumBitmapIndices to a different value nonSignerStakesAndSignature.nonSignerQuorumBitmapIndices[0] = 1; - cheats.expectRevert("RegistryCoordinator.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from after blockNumber"); + cheats.expectRevert(QuorumBitmapHistoryLib.BitmapUpdateIsAfterBlockNumber.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -373,7 +377,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // set the totalStakeIndices to a different value nonSignerStakesAndSignature.totalStakeIndices[0] = 0; - cheats.expectRevert("StakeRegistry._validateStakeUpdateAtBlockNumber: there is a newer stakeUpdate available before blockNumber"); + cheats.expectRevert(IStakeRegistryErrors.InvalidBlockNumber.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -402,7 +406,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // set the nonSignerStakeIndices to a different value nonSignerStakesAndSignature.nonSignerStakeIndices[0][0] = 1; - cheats.expectRevert("StakeRegistry._validateStakeUpdateAtBlockNumber: stakeUpdate is from after blockNumber"); + cheats.expectRevert(IStakeRegistryErrors.InvalidBlockNumber.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -423,7 +427,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // set the quorumApkIndices to a different value nonSignerStakesAndSignature.quorumApkIndices[0] = 0; - cheats.expectRevert("BLSApkRegistry.getApkHashAtBlockNumberAndIndex: not latest apk update"); + cheats.expectRevert(IBLSApkRegistryErrors.BlockNumberNotLatest.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -443,7 +447,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // set the quorumApk to a different value nonSignerStakesAndSignature.quorumApks[0] = nonSignerStakesAndSignature.quorumApks[0].negate(); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: quorumApk hash in storage does not match provided quorum apk"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InvalidQuorumApkHash.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -463,7 +467,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { // set the sigma to a different value nonSignerStakesAndSignature.sigma = nonSignerStakesAndSignature.sigma.negate(); - cheats.expectRevert("BLSSignatureChecker.checkSignatures: signature is invalid"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InvalidBLSSignature.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, @@ -505,7 +509,7 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer { bytes memory quorumNumbers = BitmapUtils.bitmapToBytesArray(0); // expect a non-specific low-level revert, since this call will ultimately fail as part of the precompile call - cheats.expectRevert("BLSSignatureChecker.checkSignatures: empty quorum input"); + cheats.expectRevert(IBLSSignatureCheckerErrors.InputEmptyQuorumNumbers.selector); blsSignatureChecker.checkSignatures( msgHash, quorumNumbers, diff --git a/test/unit/BitmapUtils.t.sol b/test/unit/BitmapUtils.t.sol index fcd742b2..a998dbe3 100644 --- a/test/unit/BitmapUtils.t.sol +++ b/test/unit/BitmapUtils.t.sol @@ -185,7 +185,7 @@ contract BitmapUtilsUnitTests_bytesArrayToBitmap is BitmapUtilsUnitTests { /// when calling orderedBytesArrayToBitmap function testFuzz_OrderedBytesArrayToBitmap_Revert_WhenNotOrdered(bytes memory originalBytesArray) public { cheats.assume(!bitmapUtilsWrapper.isArrayStrictlyAscendingOrdered(originalBytesArray)); - cheats.expectRevert("BitmapUtils.orderedBytesArrayToBitmap: orderedBytesArray is not ordered"); + cheats.expectRevert(BitmapUtils.BytesArrayNotOrdered.selector); bitmapUtilsWrapper.orderedBytesArrayToBitmap(originalBytesArray); } diff --git a/test/unit/EjectionManagerUnit.t.sol b/test/unit/EjectionManagerUnit.t.sol index 9f01af50..a95366f7 100644 --- a/test/unit/EjectionManagerUnit.t.sol +++ b/test/unit/EjectionManagerUnit.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.27; import {EjectionManager} from "../../src/EjectionManager.sol"; -import {IEjectionManager} from "../../src/interfaces/IEjectionManager.sol"; +import {IEjectionManager, IEjectionManagerErrors} from "../../src/interfaces/IEjectionManager.sol"; import "../utils/MockAVSDeployer.sol"; @@ -366,7 +366,7 @@ contract EjectionManagerUnitTests is MockAVSDeployer { function test_Revert_NotPermissioned() public { bytes32[][] memory operatorIds; - cheats.expectRevert("EjectionManager.ejectOperators: Only owner or ejector can eject"); + cheats.expectRevert(IEjectionManagerErrors.OnlyOwnerOrEjector.selector); ejectionManager.ejectOperators(operatorIds); EjectionManager.QuorumEjectionParams memory _quorumEjectionParams; diff --git a/test/unit/IndexRegistryUnit.t.sol b/test/unit/IndexRegistryUnit.t.sol index 36d7dc69..79d74e91 100644 --- a/test/unit/IndexRegistryUnit.t.sol +++ b/test/unit/IndexRegistryUnit.t.sol @@ -293,6 +293,7 @@ contract IndexRegistryUnitTests_configAndGetters is IndexRegistryUnitTests { // should revert with startBlocknumber cheats.expectRevert("IndexRegistry._operatorCountAtBlockNumber: quorum did not exist at given block number"); + indexRegistry.getOperatorListAtBlockNumber( quorumNumber, startBlockNumber @@ -418,7 +419,7 @@ contract IndexRegistryUnitTests_registerOperator is IndexRegistryUnitTests { bytes memory quorumNumbers = new bytes(defaultQuorumNumber); cheats.prank(nonRegistryCoordinator); - cheats.expectRevert("IndexRegistry._checkRegistryCoordinator: caller is not the registry coordinator"); + cheats.expectRevert(IIndexRegistryErrors.OnlyRegistryCoordinator.selector); indexRegistry.registerOperator(bytes32(0), quorumNumbers); } @@ -439,7 +440,7 @@ contract IndexRegistryUnitTests_registerOperator is IndexRegistryUnitTests { // Register for invalid quorums, should revert bytes memory invalidQuorumNumbers = bitmapUtilsWrapper.bitmapToBytesArray(invalidBitmap); cheats.prank(address(registryCoordinator)); - cheats.expectRevert("IndexRegistry.registerOperator: quorum does not exist"); + cheats.expectRevert(IIndexRegistryErrors.QuorumDoesNotExist.selector); indexRegistry.registerOperator(operatorId1, invalidQuorumNumbers); } @@ -699,7 +700,7 @@ contract IndexRegistryUnitTests_deregisterOperator is IndexRegistryUnitTests { bytes memory quorumNumbers = new bytes(defaultQuorumNumber); cheats.prank(nonRegistryCoordinator); - cheats.expectRevert("IndexRegistry._checkRegistryCoordinator: caller is not the registry coordinator"); + cheats.expectRevert(IIndexRegistryErrors.OnlyRegistryCoordinator.selector); indexRegistry.deregisterOperator(bytes32(0), quorumNumbers); } @@ -724,7 +725,7 @@ contract IndexRegistryUnitTests_deregisterOperator is IndexRegistryUnitTests { // Deregister for invalid quorums, should revert cheats.prank(address(registryCoordinator)); - cheats.expectRevert("IndexRegistry.registerOperator: quorum does not exist"); + cheats.expectRevert(IIndexRegistryErrors.QuorumDoesNotExist.selector); indexRegistry.deregisterOperator(operatorId1, invalidQuorumNumbers); } diff --git a/test/unit/OperatorStateRetrieverUnit.t.sol b/test/unit/OperatorStateRetrieverUnit.t.sol index e25c8af0..55f6aabd 100644 --- a/test/unit/OperatorStateRetrieverUnit.t.sol +++ b/test/unit/OperatorStateRetrieverUnit.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.27; import "../utils/MockAVSDeployer.sol"; +import {IStakeRegistryErrors} from "../../src/interfaces/IStakeRegistry.sol"; contract OperatorStateRetrieverUnitTests is MockAVSDeployer { using BN254 for BN254.G1Point; @@ -186,9 +187,7 @@ contract OperatorStateRetrieverUnitTests is MockAVSDeployer { registryCoordinator.deregisterOperator(BitmapUtils.bitmapToBytesArray(1)); // should revert because the operator was registered for the first time after the reference block number - cheats.expectRevert( - "OperatorStateRetriever.getCheckSignaturesIndices: operator must be registered at blocknumber" - ); + cheats.expectRevert(OperatorStateRetriever.OperatorNotRegistered.selector); operatorStateRetriever.getCheckSignaturesIndices( registryCoordinator, uint32(block.number), @@ -203,7 +202,7 @@ contract OperatorStateRetrieverUnitTests is MockAVSDeployer { _registerOperatorWithCoordinator(defaultOperator, 1, defaultPubKey); - cheats.expectRevert("StakeRegistry.quorumExists: quorum does not exist"); + cheats.expectRevert(IStakeRegistryErrors.QuorumDoesNotExist.selector); operatorStateRetriever.getCheckSignaturesIndices( registryCoordinator, uint32(block.number), @@ -237,9 +236,7 @@ contract OperatorStateRetrieverUnitTests is MockAVSDeployer { cheats.prank(registryCoordinator.owner()); registryCoordinator.createTotalDelegatedStakeQuorum(operatorSetParams, minimumStake, strategyParams); - cheats.expectRevert( - "StakeRegistry.getTotalStakeIndicesAtBlockNumber: quorum has no stake history at blockNumber" - ); + cheats.expectRevert(IStakeRegistryErrors.EmptyStakeHistory.selector); operatorStateRetriever.getCheckSignaturesIndices( registryCoordinator, registrationBlockNumber + 5, diff --git a/test/unit/RegistryCoordinatorUnit.t.sol b/test/unit/RegistryCoordinatorUnit.t.sol index c3c8032d..72207dcc 100644 --- a/test/unit/RegistryCoordinatorUnit.t.sol +++ b/test/unit/RegistryCoordinatorUnit.t.sol @@ -3,6 +3,8 @@ pragma solidity ^0.8.27; import "../utils/MockAVSDeployer.sol"; import {IRegistryCoordinatorErrors} from "../../src/interfaces/IRegistryCoordinator.sol"; +import {QuorumBitmapHistoryLib} from "../../src/libraries/QuorumBitmapHistoryLib.sol"; +import {BitmapUtils} from "../../src/libraries/BitmapUtils.sol"; contract RegistryCoordinatorUnitTests is MockAVSDeployer { using BN254 for BN254.G1Point; @@ -281,7 +283,7 @@ contract RegistryCoordinatorUnitTests_RegisterOperator is RegistryCoordinatorUni quorumNumbersTooLarge[0] = 0xC0; - cheats.expectRevert("BitmapUtils.orderedBytesArrayToBitmap: bitmap exceeds max value"); + cheats.expectRevert(BitmapUtils.BitmapValueTooLarge.selector); cheats.prank(defaultOperator); registryCoordinator.registerOperator(quorumNumbersTooLarge, defaultSocket, pubkeyRegistrationParams, emptySig); } @@ -294,7 +296,7 @@ contract RegistryCoordinatorUnitTests_RegisterOperator is RegistryCoordinatorUni quorumNumbersNotCreated[0] = 0x0B; cheats.prank(defaultOperator); - cheats.expectRevert("BitmapUtils.orderedBytesArrayToBitmap: bitmap exceeds max value"); + cheats.expectRevert(BitmapUtils.BitmapValueTooLarge.selector); registryCoordinator.registerOperator(quorumNumbersNotCreated, defaultSocket, pubkeyRegistrationParams, emptySig); } @@ -523,7 +525,7 @@ contract RegistryCoordinatorUnitTests_RegisterOperator is RegistryCoordinatorUni quorumNumbersTooLarge[0] = 0xC0; - cheats.expectRevert("BitmapUtils.orderedBytesArrayToBitmap: bitmap exceeds max value"); + cheats.expectRevert(BitmapUtils.BitmapValueTooLarge.selector); registryCoordinator._registerOperatorExternal(defaultOperator, defaultOperatorId, quorumNumbersTooLarge, defaultSocket, emptySig); } @@ -1298,7 +1300,7 @@ contract RegistryCoordinatorUnitTests_DeregisterOperator_EjectOperator is Regist uint192 emptyBitmap = 0; // try an incorrect blockNumber input and confirm reversion - cheats.expectRevert("RegistryCoordinator.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from after blockNumber"); + cheats.expectRevert(QuorumBitmapHistoryLib.BitmapUpdateIsAfterBlockNumber.selector); uint192 returnVal = registryCoordinator.getQuorumBitmapAtBlockNumberByIndex(operatorId, blockNumber, index); blockNumber = registrationBlockNumber; @@ -1311,7 +1313,7 @@ contract RegistryCoordinatorUnitTests_DeregisterOperator_EjectOperator is Regist // try an incorrect index input and confirm reversion index = 1; - cheats.expectRevert("RegistryCoordinator.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from after blockNumber"); + cheats.expectRevert(QuorumBitmapHistoryLib.BitmapUpdateIsAfterBlockNumber.selector); returnVal = registryCoordinator.getQuorumBitmapAtBlockNumberByIndex(operatorId, blockNumber, index); blockNumber = deregistrationBlockNumber; @@ -1324,7 +1326,7 @@ contract RegistryCoordinatorUnitTests_DeregisterOperator_EjectOperator is Regist // try an incorrect index input and confirm reversion index = 0; - cheats.expectRevert("RegistryCoordinator.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from before blockNumber"); + cheats.expectRevert(QuorumBitmapHistoryLib.NextBitmapUpdateIsBeforeBlockNumber.selector); returnVal = registryCoordinator.getQuorumBitmapAtBlockNumberByIndex(operatorId, blockNumber, index); } } @@ -1669,7 +1671,7 @@ contract RegistryCoordinatorUnitTests_UpdateOperators is RegistryCoordinatorUnit address[][] memory operatorsToUpdate = new address[][](1); cheats.prank(defaultOperator); - cheats.expectRevert("BitmapUtils.orderedBytesArrayToBitmap: bitmap exceeds max value"); + cheats.expectRevert(BitmapUtils.BitmapValueTooLarge.selector); registryCoordinator.updateOperatorsForQuorum(operatorsToUpdate, quorumNumbersNotCreated); } diff --git a/test/unit/ServiceManagerBase.t.sol b/test/unit/ServiceManagerBase.t.sol index 8d37f9d6..ca3d0e9f 100644 --- a/test/unit/ServiceManagerBase.t.sol +++ b/test/unit/ServiceManagerBase.t.sol @@ -12,6 +12,7 @@ import {PermissionController} from "eigenlayer-contracts/src/contracts/permissio import {StrategyBase} from "eigenlayer-contracts/src/contracts/strategies/StrategyBase.sol"; import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; import {IServiceManagerBaseEvents} from "../events/IServiceManagerBaseEvents.sol"; +import {IServiceManagerErrors} from "../../src/interfaces/IServiceManager.sol"; import "../utils/MockAVSDeployer.sol"; @@ -225,9 +226,7 @@ contract ServiceManagerBase_UnitTests is MockAVSDeployer, IServiceManagerBaseEve IRewardsCoordinator.RewardsSubmission[] memory rewardsSubmissions; cheats.prank(caller); - cheats.expectRevert( - "ServiceManagerBase.onlyRewardsInitiator: caller is not the rewards initiator" - ); + cheats.expectRevert(IServiceManagerErrors.OnlyRewardsInitiator.selector); serviceManager.createAVSRewardsSubmission(rewardsSubmissions); } diff --git a/test/unit/StakeRegistryUnit.t.sol b/test/unit/StakeRegistryUnit.t.sol index 7e8f483e..a21a8c39 100644 --- a/test/unit/StakeRegistryUnit.t.sol +++ b/test/unit/StakeRegistryUnit.t.sol @@ -6,7 +6,7 @@ import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.so import "test/utils/MockAVSDeployer.sol"; import {StakeRegistry} from "src/StakeRegistry.sol"; -import {IStakeRegistry} from "src/interfaces/IStakeRegistry.sol"; +import {IStakeRegistry, IStakeRegistryErrors} from "src/interfaces/IStakeRegistry.sol"; import {IStakeRegistryEvents} from "test/events/IStakeRegistryEvents.sol"; import "../utils/MockAVSDeployer.sol"; @@ -580,9 +580,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { uint96 minimumStake, IStakeRegistry.StrategyParams[] memory strategyParams ) public { - cheats.expectRevert( - "StakeRegistry.onlyRegistryCoordinator: caller is not the RegistryCoordinator" - ); + cheats.expectRevert(IStakeRegistryErrors.OnlyRegistryCoordinator.selector); stakeRegistry.initializeDelegatedStakeQuorum(quorumNumber, minimumStake, strategyParams); } @@ -591,7 +589,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { uint96 minimumStake, IStakeRegistry.StrategyParams[] memory strategyParams ) public fuzzOnlyInitializedQuorums(quorumNumber) { - cheats.expectRevert("StakeRegistry.initializeQuorum: quorum already exists"); + cheats.expectRevert(IStakeRegistryErrors.QuorumAlreadyExists.selector); cheats.prank(address(registryCoordinator)); stakeRegistry.initializeDelegatedStakeQuorum(quorumNumber, minimumStake, strategyParams); } @@ -603,7 +601,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { cheats.assume(quorumNumber >= nextQuorum); IStakeRegistry.StrategyParams[] memory strategyParams = new IStakeRegistry.StrategyParams[](0); - cheats.expectRevert("StakeRegistry._addStrategyParams: no strategies provided"); + cheats.expectRevert(IStakeRegistryErrors.InputArrayLengthZero.selector); cheats.prank(address(registryCoordinator)); stakeRegistry.initializeDelegatedStakeQuorum(quorumNumber, minimumStake, strategyParams); @@ -613,7 +611,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { IStrategy(address(uint160(uint256(keccak256(abi.encodePacked(i)))))), uint96(1) ); } - cheats.expectRevert("StakeRegistry._addStrategyParams: exceed MAX_WEIGHING_FUNCTION_LENGTH"); + cheats.expectRevert(IStakeRegistryErrors.InputArrayLengthMismatch.selector); cheats.prank(address(registryCoordinator)); stakeRegistry.initializeDelegatedStakeQuorum(quorumNumber, minimumStake, strategyParams); } @@ -731,9 +729,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { uint8 quorumNumber, uint96 minimumStakeForQuorum ) public fuzzOnlyInitializedQuorums(quorumNumber) { - cheats.expectRevert( - "StakeRegistry.onlyCoordinatorOwner: caller is not the owner of the registryCoordinator" - ); + cheats.expectRevert(IStakeRegistryErrors.OnlyRegistryCoordinatorOwner.selector); stakeRegistry.setMinimumStakeForQuorum(quorumNumber, minimumStakeForQuorum); } @@ -743,7 +739,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { ) public { // quorums [0,nextQuorum) are initialized, so use an invalid quorumNumber cheats.assume(quorumNumber >= nextQuorum); - cheats.expectRevert("StakeRegistry.quorumExists: quorum does not exist"); + cheats.expectRevert(IStakeRegistryErrors.QuorumDoesNotExist.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.setMinimumStakeForQuorum(quorumNumber, minimumStakeForQuorum); } @@ -771,9 +767,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { uint8 quorumNumber, IStakeRegistry.StrategyParams[] memory strategyParams ) public fuzzOnlyInitializedQuorums(quorumNumber) { - cheats.expectRevert( - "StakeRegistry.onlyCoordinatorOwner: caller is not the owner of the registryCoordinator" - ); + cheats.expectRevert(IStakeRegistryErrors.OnlyRegistryCoordinatorOwner.selector); stakeRegistry.addStrategies(quorumNumber, strategyParams); } @@ -783,7 +777,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { ) public { // quorums [0,nextQuorum) are initialized, so use an invalid quorumNumber cheats.assume(quorumNumber >= nextQuorum); - cheats.expectRevert("StakeRegistry.quorumExists: quorum does not exist"); + cheats.expectRevert(IStakeRegistryErrors.QuorumDoesNotExist.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.addStrategies(quorumNumber, strategyParams); } @@ -798,7 +792,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { strategyParams[0] = IStakeRegistry.StrategyParams(strat, uint96(WEIGHTING_DIVISOR)); strategyParams[1] = IStakeRegistry.StrategyParams(strat, uint96(WEIGHTING_DIVISOR)); - cheats.expectRevert("StakeRegistry._addStrategyParams: cannot add same strategy 2x"); + cheats.expectRevert(IStakeRegistryErrors.InputDuplicateStrategy.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.addStrategies(quorumNumber, strategyParams); } @@ -812,9 +806,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { new IStakeRegistry.StrategyParams[](2); strategyParams[0] = IStakeRegistry.StrategyParams(strat, 0); - cheats.expectRevert( - "StakeRegistry._addStrategyParams: cannot add strategy with zero weight" - ); + cheats.expectRevert(IStakeRegistryErrors.InputMultiplierZero.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.addStrategies(quorumNumber, strategyParams); } @@ -874,9 +866,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { uint8 quorumNumber, uint256[] memory indicesToRemove ) public fuzzOnlyInitializedQuorums(quorumNumber) { - cheats.expectRevert( - "StakeRegistry.onlyCoordinatorOwner: caller is not the owner of the registryCoordinator" - ); + cheats.expectRevert(IStakeRegistryErrors.OnlyRegistryCoordinatorOwner.selector); stakeRegistry.removeStrategies(quorumNumber, indicesToRemove); } @@ -886,7 +876,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { ) public { // quorums [0,nextQuorum) are initialized, so use an invalid quorumNumber cheats.assume(quorumNumber >= nextQuorum); - cheats.expectRevert("StakeRegistry.quorumExists: quorum does not exist"); + cheats.expectRevert(IStakeRegistryErrors.QuorumDoesNotExist.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.removeStrategies(quorumNumber, indicesToRemove); } @@ -916,7 +906,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { uint8 quorumNumber = _initializeQuorum(minimumStake, numStrategiesToAdd); uint256[] memory indicesToRemove = new uint256[](0); - cheats.expectRevert("StakeRegistry.removeStrategies: no indices to remove provided"); + cheats.expectRevert(IStakeRegistryErrors.InputArrayLengthZero.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.removeStrategies(quorumNumber, indicesToRemove); } @@ -977,9 +967,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { uint256[] calldata strategyIndices, uint96[] calldata newMultipliers ) public fuzzOnlyInitializedQuorums(quorumNumber) { - cheats.expectRevert( - "StakeRegistry.onlyCoordinatorOwner: caller is not the owner of the registryCoordinator" - ); + cheats.expectRevert(IStakeRegistryErrors.OnlyRegistryCoordinatorOwner.selector); stakeRegistry.modifyStrategyParams(quorumNumber, strategyIndices, newMultipliers); } @@ -990,7 +978,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { ) public { // quorums [0,nextQuorum) are initialized, so use an invalid quorumNumber cheats.assume(quorumNumber >= nextQuorum); - cheats.expectRevert("StakeRegistry.quorumExists: quorum does not exist"); + cheats.expectRevert(IStakeRegistryErrors.QuorumDoesNotExist.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.modifyStrategyParams(quorumNumber, strategyIndices, newMultipliers); } @@ -1001,7 +989,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { { uint256[] memory strategyIndices = new uint256[](0); uint96[] memory newMultipliers = new uint96[](0); - cheats.expectRevert("StakeRegistry.modifyStrategyParams: no strategy indices provided"); + cheats.expectRevert(IStakeRegistryErrors.InputArrayLengthZero.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.modifyStrategyParams(quorumNumber, strategyIndices, newMultipliers); } @@ -1013,7 +1001,7 @@ contract StakeRegistryUnitTests_Config is StakeRegistryUnitTests { ) public fuzzOnlyInitializedQuorums(quorumNumber) { cheats.assume(strategyIndices.length != newMultipliers.length); cheats.assume(strategyIndices.length > 0); - cheats.expectRevert("StakeRegistry.modifyStrategyParams: input length mismatch"); + cheats.expectRevert(IStakeRegistryErrors.InputArrayLengthMismatch.selector); cheats.prank(registryCoordinatorOwner); stakeRegistry.modifyStrategyParams(quorumNumber, strategyIndices, newMultipliers); } @@ -1072,9 +1060,7 @@ contract StakeRegistryUnitTests_Register is StakeRegistryUnitTests { function test_registerOperator_Revert_WhenNotRegistryCoordinator() public { (address operator, bytes32 operatorId) = _selectNewOperator(); - cheats.expectRevert( - "StakeRegistry.onlyRegistryCoordinator: caller is not the RegistryCoordinator" - ); + cheats.expectRevert(IStakeRegistryErrors.OnlyRegistryCoordinator.selector); stakeRegistry.registerOperator(operator, operatorId, initializedQuorumBytes); } @@ -1084,7 +1070,7 @@ contract StakeRegistryUnitTests_Register is StakeRegistryUnitTests { // Get a list of valid quorums ending in an invalid quorum number bytes memory invalidQuorums = _fuzz_getInvalidQuorums(rand); - cheats.expectRevert("StakeRegistry.quorumExists: quorum does not exist"); + cheats.expectRevert(IStakeRegistryErrors.QuorumDoesNotExist.selector); cheats.prank(address(registryCoordinator)); stakeRegistry.registerOperator(setup.operator, setup.operatorId, invalidQuorums); } @@ -1118,9 +1104,7 @@ contract StakeRegistryUnitTests_Register is StakeRegistryUnitTests { } // Attempt to register - cheats.expectRevert( - "StakeRegistry.registerOperator: Operator does not meet minimum stake requirement for quorum" - ); + cheats.expectRevert(IStakeRegistryErrors.BelowMinimumStakeRequirement.selector); cheats.prank(address(registryCoordinator)); stakeRegistry.registerOperator(operator, operatorId, quorumNumbers); } @@ -1426,9 +1410,7 @@ contract StakeRegistryUnitTests_Deregister is StakeRegistryUnitTests { fuzzy_addtlStake: 0 }); - cheats.expectRevert( - "StakeRegistry.onlyRegistryCoordinator: caller is not the RegistryCoordinator" - ); + cheats.expectRevert(IStakeRegistryErrors.OnlyRegistryCoordinator.selector); stakeRegistry.deregisterOperator(setup.operatorId, setup.quorumsToRemove); } @@ -1443,7 +1425,7 @@ contract StakeRegistryUnitTests_Deregister is StakeRegistryUnitTests { // Get a list of valid quorums ending in an invalid quorum number bytes memory invalidQuorums = _fuzz_getInvalidQuorums(rand); - cheats.expectRevert("StakeRegistry.quorumExists: quorum does not exist"); + cheats.expectRevert(IStakeRegistryErrors.QuorumDoesNotExist.selector); cheats.prank(address(registryCoordinator)); stakeRegistry.registerOperator(setup.operator, setup.operatorId, invalidQuorums); } @@ -1790,9 +1772,7 @@ contract StakeRegistryUnitTests_StakeUpdates is StakeRegistryUnitTests { UpdateSetup memory setup = _fuzz_setupUpdateOperatorStake({registeredFor: initializedQuorumBitmap, fuzzy_Delta: 0}); - cheats.expectRevert( - "StakeRegistry.onlyRegistryCoordinator: caller is not the RegistryCoordinator" - ); + cheats.expectRevert(IStakeRegistryErrors.OnlyRegistryCoordinator.selector); stakeRegistry.updateOperatorStake(setup.operator, setup.operatorId, setup.quorumNumbers); } @@ -1804,7 +1784,7 @@ contract StakeRegistryUnitTests_StakeUpdates is StakeRegistryUnitTests { // Get a list of valid quorums ending in an invalid quorum number bytes memory invalidQuorums = _fuzz_getInvalidQuorums(rand); - cheats.expectRevert("StakeRegistry.quorumExists: quorum does not exist"); + cheats.expectRevert(IStakeRegistryErrors.QuorumDoesNotExist.selector); cheats.prank(address(registryCoordinator)); stakeRegistry.updateOperatorStake(setup.operator, setup.operatorId, invalidQuorums); }