diff --git a/.gitmodules b/.gitmodules index 2aa603d589..f07a5f3d3c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "solidity/lib/eigenlayer-middleware"] path = solidity/lib/eigenlayer-middleware url = https://github.com/Layr-Labs/eigenlayer-middleware +[submodule "solidity/lib/eigenlayer-contracts"] + path = solidity/lib/eigenlayer-contracts + url = https://github.com/Layr-Labs/eigenlayer-contracts diff --git a/solidity/contracts/avs/HyperlaneServiceManager.sol b/solidity/contracts/avs/HyperlaneServiceManager.sol new file mode 100644 index 0000000000..d1e88db3f8 --- /dev/null +++ b/solidity/contracts/avs/HyperlaneServiceManager.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.0; + +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +import {ISignatureUtils} from "@eigenlayer/core/interfaces/ISignatureUtils.sol"; +import {IAVSDirectory} from "@eigenlayer/core/interfaces/IAVSDirectory.sol"; + +import {IStakeRegistry} from "@eigenlayer/middleware/interfaces/IStakeRegistry.sol"; +import {IServiceManager} from "@eigenlayer/middleware/interfaces/IServiceManager.sol"; + +contract HyperlaneServiceManager is IServiceManager, OwnableUpgradeable { + IStakeRegistry internal immutable stakeRegistry; + IAVSDirectory internal immutable elAvsDirectory; + + /// @notice when applied to a function, only allows the ECDSAStakeRegistry to call it + modifier onlyStakeRegistry() { + require( + msg.sender == address(stakeRegistry), + "HyperlaneServiceManager: caller is not the stake registry" + ); + _; + } + + constructor(IAVSDirectory _avsDirectory, IStakeRegistry _stakeRegistry) { + elAvsDirectory = _avsDirectory; + stakeRegistry = _stakeRegistry; + _disableInitializers(); + } + + /** + * @notice Updates the metadata URI for the AVS + * @param _metadataURI is the metadata URI for the AVS + * @dev only callable by the owner + */ + function updateAVSMetadataURI( + string memory _metadataURI + ) public virtual onlyOwner { + elAvsDirectory.updateAVSMetadataURI(_metadataURI); + } + + /** + * @notice Forwards a call to EigenLayer's AVSDirectory contract to confirm operator registration 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 + ) public virtual onlyStakeRegistry { + elAvsDirectory.registerOperatorToAVS(operator, operatorSignature); + } + + /** + * @notice Forwards a call to EigenLayer's AVSDirectory contract to confirm operator deregistration from the AVS + * @param operator The address of the operator to deregister. + */ + function deregisterOperatorFromAVS( + address operator + ) public virtual onlyStakeRegistry { + elAvsDirectory.deregisterOperatorFromAVS(operator); + } + + /** + * @notice Returns the list of strategies that the AVS supports for restaking + * @dev This function is intended to be called off-chain + * @dev No guarantee is made on uniqueness of each element in the returned array. + * The off-chain service should do that validation separately + */ + function getRestakeableStrategies() + external + view + returns (address[] memory) + { + // TODO + return new address[](0); + } + + function getOperatorRestakedStrategies( + address operator + ) external view returns (address[] memory) { + // TODO + return new address[](0); + } + + /// @notice Returns the EigenLayer AVSDirectory contract. + function avsDirectory() external view override returns (address) { + return address(elAvsDirectory); + } + + // storage gap for upgradeability + // slither-disable-next-line shadowing-state + uint256[50] private __GAP; +} diff --git a/solidity/contracts/interfaces/avs/ITownCrier.sol b/solidity/contracts/interfaces/avs/ITownCrier.sol new file mode 100644 index 0000000000..c980bdd3ef --- /dev/null +++ b/solidity/contracts/interfaces/avs/ITownCrier.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.0; + +/*@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@ HYPERLANE @@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ + @@@@@@@@@ @@@@@@@@@ +@@@@@@@@@ @@@@@@@@*/ + +interface ITownCrier { + function challengeDelayBlocks() external view returns (uint256); + function handleChallenge(address operator) external; +} diff --git a/solidity/lib/eigenlayer-contracts b/solidity/lib/eigenlayer-contracts new file mode 160000 index 0000000000..7229f2b426 --- /dev/null +++ b/solidity/lib/eigenlayer-contracts @@ -0,0 +1 @@ +Subproject commit 7229f2b426b6f2a24c7795b1a4687a010eac8ef2 diff --git a/solidity/lib/eigenlayer-middleware b/solidity/lib/eigenlayer-middleware index 5273cd18de..6454c05bee 160000 --- a/solidity/lib/eigenlayer-middleware +++ b/solidity/lib/eigenlayer-middleware @@ -1 +1 @@ -Subproject commit 5273cd18deaddbadb63700440ea12b69627ec446 +Subproject commit 6454c05beec77a165211f081b50905c516fc7777 diff --git a/solidity/remappings.txt b/solidity/remappings.txt index 1492dd8d72..3ba4c0f841 100644 --- a/solidity/remappings.txt +++ b/solidity/remappings.txt @@ -1,5 +1,8 @@ @openzeppelin=../node_modules/@openzeppelin +@openzeppelin/contracts-upgradeable/=../node_modules/@openzeppelin/contracts-upgradeable/ @layerzerolabs=../node_modules/@layerzerolabs @eth-optimism=../node_modules/@eth-optimism ds-test/=lib/forge-std/lib/ds-test/src/ forge-std/=lib/forge-std/src/ +@eigenlayer/core/=lib/eigenlayer-contracts/src/contracts/ +@eigenlayer/middleware/=lib/eigenlayer-middleware/src/