From fcb32f5771bf586243084d6a8a0e4b6c33d4d0c1 Mon Sep 17 00:00:00 2001 From: Michael Sun <35479365+8sunyuan@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:09:56 -0500 Subject: [PATCH] refactor: decouple AVS<>Operator mapping from DelegationManager (#403) * refactor: initial draft * fix: revert require chages * fix: small nits --- src/contracts/core/AVSDirectory.sol | 174 ++++++++++++++++++ src/contracts/core/AVSDirectoryStorage.sol | 46 +++++ src/contracts/core/DelegationManager.sol | 104 +---------- .../core/DelegationManagerStorage.sol | 13 +- src/contracts/interfaces/IAVSDirectory.sol | 67 +++++++ .../interfaces/IDelegationManager.sol | 61 ------ src/test/unit/AVSDirectoryUnit.t.sol | 104 +++++++++++ src/test/unit/DelegationUnit.t.sol | 105 ----------- 8 files changed, 393 insertions(+), 281 deletions(-) create mode 100644 src/contracts/core/AVSDirectory.sol create mode 100644 src/contracts/core/AVSDirectoryStorage.sol create mode 100644 src/contracts/interfaces/IAVSDirectory.sol create mode 100644 src/test/unit/AVSDirectoryUnit.t.sol diff --git a/src/contracts/core/AVSDirectory.sol b/src/contracts/core/AVSDirectory.sol new file mode 100644 index 000000000..98f7d9797 --- /dev/null +++ b/src/contracts/core/AVSDirectory.sol @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity =0.8.12; + +import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; +import "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; +import "@openzeppelin-upgrades/contracts/security/ReentrancyGuardUpgradeable.sol"; +import "../permissions/Pausable.sol"; +import "../libraries/EIP1271SignatureUtils.sol"; +import "./AVSDirectoryStorage.sol"; + +contract AVSDirectory is + Initializable, + OwnableUpgradeable, + Pausable, + AVSDirectoryStorage, + ReentrancyGuardUpgradeable +{ + // @dev Index for flag that pauses operator register/deregister to avs when set. + uint8 internal constant PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS = 0; + + // @dev Chain ID at the time of contract deployment + uint256 internal immutable ORIGINAL_CHAIN_ID; + + /******************************************************************************* + INITIALIZING FUNCTIONS + *******************************************************************************/ + + /** + * @dev Initializes the immutable addresses of the strategy mananger, delegationManager, slasher, + * and eigenpodManager contracts + */ + constructor(IDelegationManager _delegation) AVSDirectoryStorage(_delegation) { + _disableInitializers(); + ORIGINAL_CHAIN_ID = block.chainid; + } + + /** + * @dev Initializes the addresses of the initial owner, pauser registry, and paused status. + * minWithdrawalDelayBlocks is set only once here + */ + function initialize( + address initialOwner, + IPauserRegistry _pauserRegistry, + uint256 initialPausedStatus + ) external initializer { + _initializePauser(_pauserRegistry, initialPausedStatus); + _DOMAIN_SEPARATOR = _calculateDomainSeparator(); + _transferOwnership(initialOwner); + } + + /******************************************************************************* + EXTERNAL FUNCTIONS + *******************************************************************************/ + + + /** + * @notice Called by the AVS's service manager contract to register an operator with the avs. + * @param operator The address of the operator to register. + * @param operatorSignature The signature, salt, and expiry of the operator's signature. + */ + function registerOperatorToAVS( + address operator, + ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature + ) external onlyWhenNotPaused(PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS) { + + require( + operatorSignature.expiry >= block.timestamp, + "AVSDirectory.registerOperatorToAVS: operator signature expired" + ); + require( + avsOperatorStatus[msg.sender][operator] != OperatorAVSRegistrationStatus.REGISTERED, + "AVSDirectory.registerOperatorToAVS: operator already registered" + ); + require( + !operatorSaltIsSpent[operator][operatorSignature.salt], + "AVSDirectory.registerOperatorToAVS: salt already spent" + ); + require( + delegation.isOperator(operator), + "AVSDirectory.registerOperatorToAVS: operator not registered to EigenLayer yet"); + + // Calculate the digest hash + bytes32 operatorRegistrationDigestHash = calculateOperatorAVSRegistrationDigestHash({ + operator: operator, + avs: msg.sender, + salt: operatorSignature.salt, + expiry: operatorSignature.expiry + }); + + // Check that the signature is valid + EIP1271SignatureUtils.checkSignature_EIP1271( + operator, + operatorRegistrationDigestHash, + operatorSignature.signature + ); + + // Set the operator as registered + avsOperatorStatus[msg.sender][operator] = OperatorAVSRegistrationStatus.REGISTERED; + + // Mark the salt as spent + operatorSaltIsSpent[operator][operatorSignature.salt] = true; + + emit OperatorAVSRegistrationStatusUpdated(operator, msg.sender, OperatorAVSRegistrationStatus.REGISTERED); + } + + /** + * @notice Called by an avs to deregister an operator with the avs. + * @param operator The address of the operator to deregister. + */ + function deregisterOperatorFromAVS(address operator) external onlyWhenNotPaused(PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS) { + require( + avsOperatorStatus[msg.sender][operator] == OperatorAVSRegistrationStatus.REGISTERED, + "AVSDirectory.deregisterOperatorFromAVS: operator not registered" + ); + + // Set the operator as deregistered + avsOperatorStatus[msg.sender][operator] = OperatorAVSRegistrationStatus.UNREGISTERED; + + emit OperatorAVSRegistrationStatusUpdated(operator, msg.sender, OperatorAVSRegistrationStatus.UNREGISTERED); + } + + /** + * @notice Called by an avs to emit an `AVSMetadataURIUpdated` event indicating the information has updated. + * @param metadataURI The URI for metadata associated with an avs + */ + function updateAVSMetadataURI(string calldata metadataURI) external { + emit AVSMetadataURIUpdated(msg.sender, metadataURI); + } + + /******************************************************************************* + VIEW FUNCTIONS + *******************************************************************************/ + + /** + * @notice Calculates the digest hash to be signed by an operator to register with an AVS + * @param operator The account registering as an operator + * @param avs The address of the service manager contract for the AVS that the operator is registering to + * @param salt A unique and single use value associated with the approver signature. + * @param expiry Time after which the approver's signature becomes invalid + */ + function calculateOperatorAVSRegistrationDigestHash( + address operator, + address avs, + bytes32 salt, + uint256 expiry + ) public view returns (bytes32) { + // calculate the struct hash + bytes32 structHash = keccak256( + abi.encode(OPERATOR_AVS_REGISTRATION_TYPEHASH, operator, avs, salt, expiry) + ); + // calculate the digest hash + bytes32 digestHash = keccak256( + abi.encodePacked("\x19\x01", domainSeparator(), structHash) + ); + return digestHash; + } + + /** + * @notice Getter function for the current EIP-712 domain separator for this contract. + * @dev The domain separator will change in the event of a fork that changes the ChainID. + */ + function domainSeparator() public view returns (bytes32) { + if (block.chainid == ORIGINAL_CHAIN_ID) { + return _DOMAIN_SEPARATOR; + } else { + return _calculateDomainSeparator(); + } + } + + // @notice Internal function for calculating the current domain separator of this contract + function _calculateDomainSeparator() internal view returns (bytes32) { + return keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes("EigenLayer")), block.chainid, address(this))); + } +} \ No newline at end of file diff --git a/src/contracts/core/AVSDirectoryStorage.sol b/src/contracts/core/AVSDirectoryStorage.sol new file mode 100644 index 000000000..ec536f76b --- /dev/null +++ b/src/contracts/core/AVSDirectoryStorage.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity =0.8.12; + +import "../interfaces/IAVSDirectory.sol"; +import "../interfaces/IStrategyManager.sol"; +import "../interfaces/IDelegationManager.sol"; +import "../interfaces/ISlasher.sol"; +import "../interfaces/IEigenPodManager.sol"; + +abstract contract AVSDirectoryStorage is IAVSDirectory { + /// @notice The EIP-712 typehash for the contract's domain + bytes32 public constant DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); + + /// @notice The EIP-712 typehash for the `Registration` struct used by the contract + bytes32 public constant OPERATOR_AVS_REGISTRATION_TYPEHASH = + keccak256("OperatorAVSRegistration(address operator,address avs,bytes32 salt,uint256 expiry)"); + + /// @notice The DelegationManager contract for EigenLayer + IDelegationManager public immutable delegation; + + /** + * @notice Original EIP-712 Domain separator for this contract. + * @dev The domain separator may change in the event of a fork that modifies the ChainID. + * Use the getter function `domainSeparator` to get the current domain separator for this contract. + */ + bytes32 internal _DOMAIN_SEPARATOR; + + /// @notice Mapping: AVS => operator => enum of operator status to the AVS + mapping(address => mapping(address => OperatorAVSRegistrationStatus)) public avsOperatorStatus; + + /// @notice Mapping: operator => 32-byte salt => whether or not the salt has already been used by the operator. + /// @dev Salt is used in the `registerOperatorToAVS` function. + mapping(address => mapping(bytes32 => bool)) public operatorSaltIsSpent; + + constructor(IDelegationManager _delegation) { + delegation = _delegation; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/src/contracts/core/DelegationManager.sol b/src/contracts/core/DelegationManager.sol index 79654c89b..ff2782ebf 100644 --- a/src/contracts/core/DelegationManager.sol +++ b/src/contracts/core/DelegationManager.sol @@ -4,10 +4,9 @@ pragma solidity =0.8.12; import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgrades/contracts/security/ReentrancyGuardUpgradeable.sol"; -import "../interfaces/ISlasher.sol"; -import "./DelegationManagerStorage.sol"; import "../permissions/Pausable.sol"; import "../libraries/EIP1271SignatureUtils.sol"; +import "./DelegationManagerStorage.sol"; /** * @title DelegationManager @@ -29,9 +28,6 @@ contract DelegationManager is Initializable, OwnableUpgradeable, Pausable, Deleg // @dev Index for flag that pauses completing existing withdrawals when set. uint8 internal constant PAUSED_EXIT_WITHDRAWAL_QUEUE = 2; - // @dev Index for flag that pauses operator register/deregister to avs when set. - uint8 internal constant PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS = 3; - // @dev Chain ID at the time of contract deployment uint256 internal immutable ORIGINAL_CHAIN_ID; @@ -136,14 +132,6 @@ contract DelegationManager is Initializable, OwnableUpgradeable, Pausable, Deleg emit OperatorMetadataURIUpdated(msg.sender, metadataURI); } - /** - * @notice Called by an avs to emit an `AVSMetadataURIUpdated` event indicating the information has updated. - * @param metadataURI The URI for metadata associated with an avs - */ - function updateAVSMetadataURI(string calldata metadataURI) external { - emit AVSMetadataURIUpdated(msg.sender, metadataURI); - } - /** * @notice Caller delegates their stake to an operator. * @param operator The account (`msg.sender`) is delegating its assets to for use in serving applications built on EigenLayer. @@ -435,72 +423,6 @@ contract DelegationManager is Initializable, OwnableUpgradeable, Pausable, Deleg } } - /** - * @notice Called by the AVS's service manager contract to register an operator with the avs. - * @param operator The address of the operator to register. - * @param operatorSignature The signature, salt, and expiry of the operator's signature. - */ - function registerOperatorToAVS( - address operator, - ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature - ) external onlyWhenNotPaused(PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS) { - - require( - operatorSignature.expiry >= block.timestamp, - "DelegationManager.registerOperatorToAVS: operator signature expired" - ); - require( - avsOperatorStatus[msg.sender][operator] != OperatorAVSRegistrationStatus.REGISTERED, - "DelegationManager.registerOperatorToAVS: operator already registered" - ); - require( - !operatorSaltIsSpent[operator][operatorSignature.salt], - "DelegationManager.registerOperatorToAVS: salt already spent" - ); - require( - isOperator(operator), - "DelegationManager.registerOperatorToAVS: operator not registered to EigenLayer yet"); - - // Calculate the digest hash - bytes32 operatorRegistrationDigestHash = calculateOperatorAVSRegistrationDigestHash({ - operator: operator, - avs: msg.sender, - salt: operatorSignature.salt, - expiry: operatorSignature.expiry - }); - - // Check that the signature is valid - EIP1271SignatureUtils.checkSignature_EIP1271( - operator, - operatorRegistrationDigestHash, - operatorSignature.signature - ); - - // Set the operator as registered - avsOperatorStatus[msg.sender][operator] = OperatorAVSRegistrationStatus.REGISTERED; - - // Mark the salt as spent - operatorSaltIsSpent[operator][operatorSignature.salt] = true; - - emit OperatorAVSRegistrationStatusUpdated(operator, msg.sender, OperatorAVSRegistrationStatus.REGISTERED); - } - - /** - * @notice Called by an avs to deregister an operator with the avs. - * @param operator The address of the operator to deregister. - */ - function deregisterOperatorFromAVS(address operator) external onlyWhenNotPaused(PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS) { - require( - avsOperatorStatus[msg.sender][operator] == OperatorAVSRegistrationStatus.REGISTERED, - "DelegationManager.deregisterOperatorFromAVS: operator not registered" - ); - - // Set the operator as deregistered - avsOperatorStatus[msg.sender][operator] = OperatorAVSRegistrationStatus.UNREGISTERED; - - emit OperatorAVSRegistrationStatusUpdated(operator, msg.sender, OperatorAVSRegistrationStatus.UNREGISTERED); - } - /** * @notice Called by owner to set the minimum withdrawal delay blocks for each passed in strategy * Note that the min number of blocks to complete a withdrawal of a strategy is @@ -1061,30 +983,6 @@ contract DelegationManager is Initializable, OwnableUpgradeable, Pausable, Deleg return approverDigestHash; } - /** - * @notice Calculates the digest hash to be signed by an operator to register with an AVS - * @param operator The account registering as an operator - * @param avs The address of the service manager contract for the AVS that the operator is registering to - * @param salt A unique and single use value associated with the approver signature. - * @param expiry Time after which the approver's signature becomes invalid - */ - function calculateOperatorAVSRegistrationDigestHash( - address operator, - address avs, - bytes32 salt, - uint256 expiry - ) public view returns (bytes32) { - // calculate the struct hash - bytes32 structHash = keccak256( - abi.encode(OPERATOR_AVS_REGISTRATION_TYPEHASH, operator, avs, salt, expiry) - ); - // calculate the digest hash - bytes32 digestHash = keccak256( - abi.encodePacked("\x19\x01", domainSeparator(), structHash) - ); - return digestHash; - } - /** * @dev Recalculates the domain separator when the chainid changes due to a fork. */ diff --git a/src/contracts/core/DelegationManagerStorage.sol b/src/contracts/core/DelegationManagerStorage.sol index 01dd0faae..104f629b0 100644 --- a/src/contracts/core/DelegationManagerStorage.sol +++ b/src/contracts/core/DelegationManagerStorage.sol @@ -25,10 +25,6 @@ abstract contract DelegationManagerStorage is IDelegationManager { bytes32 public constant DELEGATION_APPROVAL_TYPEHASH = keccak256("DelegationApproval(address staker,address operator,bytes32 salt,uint256 expiry)"); - /// @notice The EIP-712 typehash for the `Registration` struct used by the contract - bytes32 public constant OPERATOR_AVS_REGISTRATION_TYPEHASH = - keccak256("OperatorAVSRegistration(address operator,address avs,bytes32 salt,uint256 expiry)"); - /** * @notice Original EIP-712 Domain separator for this contract. * @dev The domain separator may change in the event of a fork that modifies the ChainID. @@ -99,13 +95,6 @@ abstract contract DelegationManagerStorage is IDelegationManager { /// See conversation here: https://github.com/Layr-Labs/eigenlayer-contracts/pull/365/files#r1417525270 address private __deprecated_stakeRegistry; - /// @notice Mapping: AVS => operator => enum of operator status to the AVS - mapping(address => mapping(address => OperatorAVSRegistrationStatus)) public avsOperatorStatus; - - /// @notice Mapping: operator => 32-byte salt => whether or not the salt has already been used by the operator. - /// @dev Salt is used in the `registerOperatorToAVS` function. - mapping(address => mapping(bytes32 => bool)) public operatorSaltIsSpent; - /** * @notice Minimum delay enforced by this contract per Strategy for completing queued withdrawals. Measured in blocks, and adjustable by this contract's owner, * up to a maximum of `MAX_WITHDRAWAL_DELAY_BLOCKS`. Minimum value is 0 (i.e. no delay enforced). @@ -123,5 +112,5 @@ abstract contract DelegationManagerStorage is IDelegationManager { * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[37] private __gap; + uint256[39] private __gap; } diff --git a/src/contracts/interfaces/IAVSDirectory.sol b/src/contracts/interfaces/IAVSDirectory.sol new file mode 100644 index 000000000..6187439ff --- /dev/null +++ b/src/contracts/interfaces/IAVSDirectory.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity >=0.5.0; + +import "./ISignatureUtils.sol"; + +interface IAVSDirectory is ISignatureUtils { + /// @notice Enum representing the status of an operator's registration with an AVS + enum OperatorAVSRegistrationStatus { + UNREGISTERED, // Operator not registered to AVS + REGISTERED // Operator registered to AVS + } + + /** + * @notice Emitted when @param avs indicates that they are updating their MetadataURI string + * @dev Note that these strings are *never stored in storage* and are instead purely emitted in events for off-chain indexing + */ + event AVSMetadataURIUpdated(address indexed avs, string metadataURI); + + /// @notice Emitted when an operator's registration status for an AVS is updated + event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, OperatorAVSRegistrationStatus status); + + /** + * @notice Called by an avs to register an operator with the avs. + * @param operator The address of the operator to register. + * @param operatorSignature The signature, salt, and expiry of the operator's signature. + */ + function registerOperatorToAVS( + address operator, + ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature + ) external; + + /** + * @notice Called by an avs to deregister an operator with the avs. + * @param operator The address of the operator to deregister. + */ + function deregisterOperatorFromAVS(address operator) external; + + /** + * @notice Called by an AVS to emit an `AVSMetadataURIUpdated` event indicating the information has updated. + * @param metadataURI The URI for metadata associated with an AVS + * @dev Note that the `metadataURI` is *never stored * and is only emitted in the `AVSMetadataURIUpdated` event + */ + function updateAVSMetadataURI(string calldata metadataURI) external; + + /** + * @notice Returns whether or not the salt has already been used by the operator. + * @dev Salts is used in the `registerOperatorToAVS` function. + */ + function operatorSaltIsSpent(address operator, bytes32 salt) external view returns (bool); + + /** + * @notice Calculates the digest hash to be signed by an operator to register with an AVS + * @param operator The account registering as an operator + * @param avs The AVS the operator is registering to + * @param salt A unique and single use value associated with the approver signature. + * @param expiry Time after which the approver's signature becomes invalid + */ + function calculateOperatorAVSRegistrationDigestHash( + address operator, + address avs, + bytes32 salt, + uint256 expiry + ) external view returns (bytes32); + + /// @notice The EIP-712 typehash for the Registration struct used by the contract + function OPERATOR_AVS_REGISTRATION_TYPEHASH() external view returns (bytes32); +} diff --git a/src/contracts/interfaces/IDelegationManager.sol b/src/contracts/interfaces/IDelegationManager.sol index 9892e6f89..19ae7cf88 100644 --- a/src/contracts/interfaces/IDelegationManager.sol +++ b/src/contracts/interfaces/IDelegationManager.sol @@ -100,12 +100,6 @@ interface IDelegationManager is ISignatureUtils { address withdrawer; } - /// @notice Enum representing the status of an operator's registration with an AVS - enum OperatorAVSRegistrationStatus { - UNREGISTERED, // Operator not registered to AVS - REGISTERED // Operator registered to AVS - } - // @notice Emitted when a new operator registers in EigenLayer and provides their OperatorDetails. event OperatorRegistered(address indexed operator, OperatorDetails operatorDetails); @@ -118,15 +112,6 @@ interface IDelegationManager is ISignatureUtils { */ event OperatorMetadataURIUpdated(address indexed operator, string metadataURI); - /** - * @notice Emitted when @param avs indicates that they are updating their MetadataURI string - * @dev Note that these strings are *never stored in storage* and are instead purely emitted in events for off-chain indexing - */ - event AVSMetadataURIUpdated(address indexed avs, string metadataURI); - - /// @notice Emitted when an operator's registration status for an AVS is updated - event OperatorAVSRegistrationStatusUpdated(address indexed operator, address indexed avs, OperatorAVSRegistrationStatus status); - /// @notice Emitted whenever an operator's shares are increased for a given strategy. Note that shares is the delta in the operator's shares. event OperatorSharesIncreased(address indexed operator, address staker, IStrategy strategy, uint256 shares); @@ -191,13 +176,6 @@ interface IDelegationManager is ISignatureUtils { */ function updateOperatorMetadataURI(string calldata metadataURI) external; - /** - * @notice Called by an AVS to emit an `AVSMetadataURIUpdated` event indicating the information has updated. - * @param metadataURI The URI for metadata associated with an AVS - * @dev Note that the `metadataURI` is *never stored * and is only emitted in the `AVSMetadataURIUpdated` event - */ - function updateAVSMetadataURI(string calldata metadataURI) external; - /** * @notice Caller delegates their stake to an operator. * @param operator The account (`msg.sender`) is delegating its assets to for use in serving applications built on EigenLayer. @@ -332,42 +310,6 @@ interface IDelegationManager is ISignatureUtils { uint256 shares ) external; - /** - * @notice Called by an avs to register an operator with the avs. - * @param operator The address of the operator to register. - * @param operatorSignature The signature, salt, and expiry of the operator's signature. - */ - function registerOperatorToAVS( - address operator, - ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature - ) external; - - /** - * @notice Called by an avs to deregister an operator with the avs. - * @param operator The address of the operator to deregister. - */ - function deregisterOperatorFromAVS(address operator) external; - - /** - * @notice Returns whether or not the salt has already been used by the operator. - * @dev Salts is used in the `registerOperatorToAVS` function. - */ - function operatorSaltIsSpent(address operator, bytes32 salt) external view returns (bool); - - /** - * @notice Calculates the digest hash to be signed by an operator to register with an AVS - * @param operator The account registering as an operator - * @param avs The AVS the operator is registering to - * @param salt A unique and single use value associated with the approver signature. - * @param expiry Time after which the approver's signature becomes invalid - */ - function calculateOperatorAVSRegistrationDigestHash( - address operator, - address avs, - bytes32 salt, - uint256 expiry - ) external view returns (bytes32); - /** * @notice returns the address of the operator that `staker` is delegated to. * @notice Mapping: staker => operator whom the staker is currently delegated to. @@ -496,9 +438,6 @@ interface IDelegationManager is ISignatureUtils { /// @notice The EIP-712 typehash for the DelegationApproval struct used by the contract function DELEGATION_APPROVAL_TYPEHASH() external view returns (bytes32); - /// @notice The EIP-712 typehash for the Registration struct used by the contract - function OPERATOR_AVS_REGISTRATION_TYPEHASH() external view returns (bytes32); - /** * @notice Getter function for the current EIP-712 domain separator for this contract. * diff --git a/src/test/unit/AVSDirectoryUnit.t.sol b/src/test/unit/AVSDirectoryUnit.t.sol new file mode 100644 index 000000000..9c7cd20ae --- /dev/null +++ b/src/test/unit/AVSDirectoryUnit.t.sol @@ -0,0 +1,104 @@ +// contract DelegationManagerUnitTests_operatorAVSRegisterationStatus is DelegationManagerUnitTests { +// // @notice Tests that an avs who calls `updateAVSMetadataURI` will correctly see an `AVSMetadataURIUpdated` event emitted with their input +// function testFuzz_UpdateAVSMetadataURI(string memory metadataURI) public { +// // call `updateAVSMetadataURI` and check for event +// cheats.expectEmit(true, true, true, true, address(delegationManager)); +// cheats.prank(defaultAVS); +// emit AVSMetadataURIUpdated(defaultAVS, metadataURI); +// delegationManager.updateAVSMetadataURI(metadataURI); +// } + +// // @notice Verifies an operator registers successfull to avs and see an `OperatorAVSRegistrationStatusUpdated` event emitted +// function testFuzz_registerOperatorToAVS(bytes32 salt) public { +// address operator = cheats.addr(delegationSignerPrivateKey); +// assertFalse(delegationManager.isOperator(operator), "bad test setup"); +// _registerOperatorWithBaseDetails(operator); + +// cheats.expectEmit(true, true, true, true, address(delegationManager)); +// emit OperatorAVSRegistrationStatusUpdated(operator, defaultAVS, OperatorAVSRegistrationStatus.REGISTERED); + +// uint256 expiry = type(uint256).max; + +// cheats.prank(defaultAVS); +// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( +// delegationSignerPrivateKey, +// operator, +// defaultAVS, +// salt, +// expiry +// ); + +// delegationManager.registerOperatorToAVS(operator, operatorSignature); +// } + +// // @notice Verifies an operator registers successfull to avs and see an `OperatorAVSRegistrationStatusUpdated` event emitted +// function testFuzz_revert_whenOperatorNotRegisteredToEigenLayerYet(bytes32 salt) public { +// address operator = cheats.addr(delegationSignerPrivateKey); +// assertFalse(delegationManager.isOperator(operator), "bad test setup"); + +// cheats.prank(defaultAVS); +// uint256 expiry = type(uint256).max; +// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( +// delegationSignerPrivateKey, +// operator, +// defaultAVS, +// salt, +// expiry +// ); + +// cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator not registered to EigenLayer yet"); +// delegationManager.registerOperatorToAVS(operator, operatorSignature); +// } + +// // @notice Verifies an operator registers fails when the signature is not from the operator +// function testFuzz_revert_whenSignatureAddressIsNotOperator(bytes32 salt) public { +// address operator = cheats.addr(delegationSignerPrivateKey); +// assertFalse(delegationManager.isOperator(operator), "bad test setup"); +// _registerOperatorWithBaseDetails(operator); + +// uint256 expiry = type(uint256).max; +// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( +// delegationSignerPrivateKey, +// operator, +// defaultAVS, +// salt, +// expiry +// ); + +// cheats.expectRevert("EIP1271SignatureUtils.checkSignature_EIP1271: signature not from signer"); +// cheats.prank(operator); +// delegationManager.registerOperatorToAVS(operator, operatorSignature); +// } + +// // @notice Verifies an operator registers fails when the signature expiry already expires +// function testFuzz_revert_whenExpiryHasExpired(bytes32 salt, uint256 expiry, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature) public { +// address operator = cheats.addr(delegationSignerPrivateKey); +// cheats.assume(operatorSignature.expiry < block.timestamp); + +// cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator signature expired"); +// delegationManager.registerOperatorToAVS(operator, operatorSignature); +// } + +// // @notice Verifies an operator registers fails when it's already registered to the avs +// function testFuzz_revert_whenOperatorAlreadyRegisteredToAVS(bytes32 salt) public { +// address operator = cheats.addr(delegationSignerPrivateKey); +// assertFalse(delegationManager.isOperator(operator), "bad test setup"); +// _registerOperatorWithBaseDetails(operator); + +// uint256 expiry = type(uint256).max; +// ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( +// delegationSignerPrivateKey, +// operator, +// defaultAVS, +// salt, +// expiry +// ); + +// cheats.startPrank(defaultAVS); +// delegationManager.registerOperatorToAVS(operator, operatorSignature); + +// cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator already registered"); +// delegationManager.registerOperatorToAVS(operator, operatorSignature); +// cheats.stopPrank(); +// } +// } \ No newline at end of file diff --git a/src/test/unit/DelegationUnit.t.sol b/src/test/unit/DelegationUnit.t.sol index 34a601b4b..16ed6a0b8 100644 --- a/src/test/unit/DelegationUnit.t.sol +++ b/src/test/unit/DelegationUnit.t.sol @@ -810,111 +810,6 @@ contract DelegationManagerUnitTests_RegisterModifyOperator is DelegationManagerU } } -contract DelegationManagerUnitTests_operatorAVSRegisterationStatus is DelegationManagerUnitTests { - // @notice Tests that an avs who calls `updateAVSMetadataURI` will correctly see an `AVSMetadataURIUpdated` event emitted with their input - function testFuzz_UpdateAVSMetadataURI(string memory metadataURI) public { - // call `updateAVSMetadataURI` and check for event - cheats.expectEmit(true, true, true, true, address(delegationManager)); - cheats.prank(defaultAVS); - emit AVSMetadataURIUpdated(defaultAVS, metadataURI); - delegationManager.updateAVSMetadataURI(metadataURI); - } - - // @notice Verifies an operator registers successfull to avs and see an `OperatorAVSRegistrationStatusUpdated` event emitted - function testFuzz_registerOperatorToAVS(bytes32 salt) public { - address operator = cheats.addr(delegationSignerPrivateKey); - assertFalse(delegationManager.isOperator(operator), "bad test setup"); - _registerOperatorWithBaseDetails(operator); - - cheats.expectEmit(true, true, true, true, address(delegationManager)); - emit OperatorAVSRegistrationStatusUpdated(operator, defaultAVS, OperatorAVSRegistrationStatus.REGISTERED); - - uint256 expiry = type(uint256).max; - - cheats.prank(defaultAVS); - ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( - delegationSignerPrivateKey, - operator, - defaultAVS, - salt, - expiry - ); - - delegationManager.registerOperatorToAVS(operator, operatorSignature); - } - - // @notice Verifies an operator registers successfull to avs and see an `OperatorAVSRegistrationStatusUpdated` event emitted - function testFuzz_revert_whenOperatorNotRegisteredToEigenLayerYet(bytes32 salt) public { - address operator = cheats.addr(delegationSignerPrivateKey); - assertFalse(delegationManager.isOperator(operator), "bad test setup"); - - cheats.prank(defaultAVS); - uint256 expiry = type(uint256).max; - ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( - delegationSignerPrivateKey, - operator, - defaultAVS, - salt, - expiry - ); - - cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator not registered to EigenLayer yet"); - delegationManager.registerOperatorToAVS(operator, operatorSignature); - } - - // @notice Verifies an operator registers fails when the signature is not from the operator - function testFuzz_revert_whenSignatureAddressIsNotOperator(bytes32 salt) public { - address operator = cheats.addr(delegationSignerPrivateKey); - assertFalse(delegationManager.isOperator(operator), "bad test setup"); - _registerOperatorWithBaseDetails(operator); - - uint256 expiry = type(uint256).max; - ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( - delegationSignerPrivateKey, - operator, - defaultAVS, - salt, - expiry - ); - - cheats.expectRevert("EIP1271SignatureUtils.checkSignature_EIP1271: signature not from signer"); - cheats.prank(operator); - delegationManager.registerOperatorToAVS(operator, operatorSignature); - } - - // @notice Verifies an operator registers fails when the signature expiry already expires - function testFuzz_revert_whenExpiryHasExpired(bytes32 salt, uint256 expiry, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature) public { - address operator = cheats.addr(delegationSignerPrivateKey); - cheats.assume(operatorSignature.expiry < block.timestamp); - - cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator signature expired"); - delegationManager.registerOperatorToAVS(operator, operatorSignature); - } - - // @notice Verifies an operator registers fails when it's already registered to the avs - function testFuzz_revert_whenOperatorAlreadyRegisteredToAVS(bytes32 salt) public { - address operator = cheats.addr(delegationSignerPrivateKey); - assertFalse(delegationManager.isOperator(operator), "bad test setup"); - _registerOperatorWithBaseDetails(operator); - - uint256 expiry = type(uint256).max; - ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = _getOperatorSignature( - delegationSignerPrivateKey, - operator, - defaultAVS, - salt, - expiry - ); - - cheats.startPrank(defaultAVS); - delegationManager.registerOperatorToAVS(operator, operatorSignature); - - cheats.expectRevert("DelegationManager.registerOperatorToAVS: operator already registered"); - delegationManager.registerOperatorToAVS(operator, operatorSignature); - cheats.stopPrank(); - } -} - contract DelegationManagerUnitTests_delegateTo is DelegationManagerUnitTests { function test_Revert_WhenPaused() public { // set the pausing flag