diff --git a/bolt-contracts/src/contracts/BoltManager.sol b/bolt-contracts/src/contracts/BoltManager.sol index 230440b71..32e74835e 100644 --- a/bolt-contracts/src/contracts/BoltManager.sol +++ b/bolt-contracts/src/contracts/BoltManager.sol @@ -20,15 +20,6 @@ import {MapWithTimeData} from "../lib/MapWithTimeData.sol"; import {IBoltValidators} from "../interfaces/IBoltValidators.sol"; import {IBoltManager} from "../interfaces/IBoltManager.sol"; -import {IStrategyManager} from "@eigenlayer/src/contracts/interfaces/IStrategyManager.sol"; -import {IAVSDirectory} from "@eigenlayer/src/contracts/interfaces/IAVSDirectory.sol"; -import {IDelegationManager} from "@eigenlayer/src/contracts/interfaces/IDelegationManager.sol"; -import {ISignatureUtils} from "@eigenlayer/src/contracts/interfaces/ISignatureUtils.sol"; -import {IStrategy} from "@eigenlayer/src/contracts/interfaces/IStrategy.sol"; -import {AVSDirectoryStorage} from "@eigenlayer/src/contracts/core/AVSDirectoryStorage.sol"; -import {DelegationManagerStorage} from "@eigenlayer/src/contracts/core/DelegationManagerStorage.sol"; -import {StrategyManagerStorage} from "@eigenlayer/src/contracts/core/StrategyManagerStorage.sol"; - contract BoltManager is IBoltManager, Ownable { using EnumerableSet for EnumerableSet.AddressSet; using EnumerableMap for EnumerableMap.AddressToUintMap; @@ -50,15 +41,6 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Set of Symbiotic collateral addresses that are whitelisted. EnumerableSet.AddressSet private whitelistedSymbioticCollaterals; - /// @notice Set of EigenLayer operators addresses that have opted in to Bolt Protocol. - EnumerableMap.AddressToUintMap private eigenLayerOperators; - - /// @notice Set of EigenLayer protocol strategies that are used in Bolt Protocol. - EnumerableMap.AddressToUintMap private eigenLayerStrategies; - - /// @notice Set of EigenLayer collaterals addresses that are allowed. - EnumerableSet.AddressSet private whitelistedEigenLayerCollaterals; - /// @notice Set of restaking protocols supported. Each address corresponds to the /// associated Bolt Middleware contract. EnumerableSet.AddressSet private restakingProtocols; @@ -77,15 +59,6 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Address of the Symbiotic Operator Network Opt-In contract. address public immutable SYMBIOTIC_OPERATOR_NET_OPTIN; - /// @notice Address of the EigenLayer AVS Directory contract. - AVSDirectoryStorage public immutable EIGENLAYER_AVS_DIRECTORY; - - /// @notice Address of the EigenLayer Delegation Manager contract. - DelegationManagerStorage public immutable EIGENLAYER_DELEGATION_MANAGER; - - /// @notice Address of the EigenLayer Strategy Manager contract. - StrategyManagerStorage public immutable EIGENLAYER_STRATEGY_MANAGER; - /// @notice Start timestamp of the first epoch. uint48 public immutable START_TIMESTAMP; @@ -117,10 +90,7 @@ contract BoltManager is IBoltManager, Ownable { address _symbioticNetwork, address _symbioticOperatorRegistry, address _symbioticOperatorNetOptIn, - address _symbioticVaultRegistry, - address _eigenlayerAVSDirectory, - address _eigenlayerDelegationManager, - address _eigenlayerStrategyManager + address _symbioticVaultRegistry ) Ownable(_owner) { validators = IBoltValidators(_validators); START_TIMESTAMP = Time.timestamp(); @@ -129,9 +99,6 @@ contract BoltManager is IBoltManager, Ownable { SYMBIOTIC_OPERATOR_REGISTRY = _symbioticOperatorRegistry; SYMBIOTIC_OPERATOR_NET_OPTIN = _symbioticOperatorNetOptIn; SYMBIOTIC_VAULT_REGISTRY = _symbioticVaultRegistry; - EIGENLAYER_AVS_DIRECTORY = AVSDirectoryStorage(_eigenlayerAVSDirectory); - EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage(_eigenlayerDelegationManager); - EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage(_eigenlayerStrategyManager); } // ========= VIEW FUNCTIONS ========= @@ -184,21 +151,6 @@ contract BoltManager is IBoltManager, Ownable { return whitelistedSymbioticCollaterals.contains(collateral); } - /// @notice Get the list of EigenLayer strategies addresses that are allowed. - /// @return strategies The list of strategies addresses that are allowed. - function getWhitelistedEigenLayerCollaterals() public view returns (address[] memory strategies) { - return whitelistedEigenLayerCollaterals.values(); - } - - /// @notice Check if an EigenLayer strategy address is allowed. - /// @param strategy The strategy address to check if it is allowed. - /// @return true if the strategy address is allowed, false otherwise. - function isEigenLayerCollateralWhitelisted( - address strategy - ) public view returns (bool) { - return whitelistedEigenLayerCollaterals.contains(strategy); - } - // ========= ADMIN FUNCTIONS ========= /// @notice Add a restaking protocol into Bolt @@ -233,22 +185,6 @@ contract BoltManager is IBoltManager, Ownable { whitelistedSymbioticCollaterals.remove(collateral); } - /// @notice Add a collateral address to the whitelist. - /// @param collateral The collateral address to add to the whitelist. - function addWhitelistedEigenLayerCollateral( - address collateral - ) public onlyOwner { - whitelistedEigenLayerCollaterals.add(collateral); - } - - /// @notice Remove a collateral address from the whitelist. - /// @param collateral The collateral address to remove from the whitelist. - function removeWhitelistedEigenLayerCollateral( - address collateral - ) public onlyOwner { - whitelistedEigenLayerCollaterals.remove(collateral); - } - // ========= SYMBIOTIC MIDDLEWARE LOGIC ========= /// @notice Allow an operator to signal opt-in to Bolt Protocol. @@ -521,269 +457,6 @@ contract BoltManager is IBoltManager, Ownable { } } - // ========= EIGENLAYER MIDDLEWARE LOGIC ========= - - /// @notice Allow an operator to signal opt-in to Bolt Protocol. - /// @param operator The operator address to signal opt-in for. - function registerEigenLayerOperator( - address operator - ) public { - if (eigenLayerOperators.contains(operator)) { - revert AlreadyRegistered(); - } - - if (!EIGENLAYER_DELEGATION_MANAGER.isOperator(operator)) { - revert NotOperator(); - } - - if (!checkIfEigenLayerOperatorRegisteredToAVS(operator)) { - revert OperatorNotRegisteredToAVS(); - } - - eigenLayerOperators.add(operator); - eigenLayerOperators.enable(operator); - } - - /// @notice Allow an operator to signal indefinite opt-out from Bolt Protocol. - /// @dev Pausing activity does not prevent the operator from being slashable for - /// the current network epoch until the end of the slashing window. - function pauseEigenLayerOperator() public { - if (!eigenLayerOperators.contains(msg.sender)) { - revert NotRegistered(); - } - - eigenLayerOperators.disable(msg.sender); - } - - /// @notice Allow a disabled operator to signal opt-in to Bolt Protocol. - function unpauseEigenLayerOperator() public { - if (!eigenLayerOperators.contains(msg.sender)) { - revert NotRegistered(); - } - - eigenLayerOperators.enable(msg.sender); - } - - function registerEigenLayerStrategy( - address strategy - ) public { - if (eigenLayerStrategies.contains(strategy)) { - revert AlreadyRegistered(); - } - - if (!EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit(IStrategy(strategy))) { - revert StrategyNotAllowed(); - } - - if (!isEigenLayerCollateralWhitelisted(address(IStrategy(strategy).underlyingToken()))) { - revert CollateralNotWhitelisted(); - } - - eigenLayerStrategies.add(strategy); - eigenLayerStrategies.enable(strategy); - } - - /// @notice Allow a strategy to signal indefinite opt-out from Bolt Protocol. - function pauseEigenLayerStrategy() public { - if (!eigenLayerStrategies.contains(msg.sender)) { - revert NotRegistered(); - } - - eigenLayerStrategies.disable(msg.sender); - } - - /// @notice Allow a disabled strategy to signal opt-in to Bolt Protocol. - function unpauseEigenLayerStrategy() public { - if (!eigenLayerStrategies.contains(msg.sender)) { - revert NotRegistered(); - } - - eigenLayerStrategies.enable(msg.sender); - } - - /// @notice Check if a strategy is currently enabled to work in Bolt Protocol. - /// @param strategy The strategy address to check the enabled status for. - /// @return True if the strategy is enabled, false otherwise. - function isEigenLayerStrategyEnabled( - address strategy - ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.getTimes(strategy); - return enabledTime != 0 && disabledTime == 0; - } - - /// @notice Check if an operator is currently enabled to work in Bolt Protocol. - /// @param operator The operator address to check the enabled status for. - /// @return True if the operator is enabled, false otherwise. - function isEigenLayerOperatorEnabled( - address operator - ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); - return enabledTime != 0 && disabledTime == 0; - } - - /// @notice Get the status of multiple proposers, given their pubkey hashes. - /// @param pubkeyHashes The pubkey hashes of the proposers to get the status for. - /// @return statuses The statuses of the proposers, including their operator and active stake. - function getEigenLayerProposersStatus( - bytes32[] memory pubkeyHashes - ) public view returns (ProposerStatus[] memory statuses) { - statuses = new ProposerStatus[](pubkeyHashes.length); - for (uint256 i = 0; i < pubkeyHashes.length; ++i) { - statuses[i] = getEigenLayerProposerStatus(pubkeyHashes[i]); - } - } - - /// @notice Get the status of a proposer, given their pubkey hash. - /// @param pubkeyHash The pubkey hash of the proposer to get the status for. - /// @return status The status of the proposer, including their operator and active stake. - function getEigenLayerProposerStatus( - bytes32 pubkeyHash - ) public view returns (ProposerStatus memory status) { - if (pubkeyHash == bytes32(0)) { - revert InvalidQuery(); - } - - uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); - - address operator = validator.authorizedOperator; - - status.pubkeyHash = pubkeyHash; - status.active = validator.exists; - status.operator = operator; - - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); - if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { - return status; - } - - status.collaterals = new address[](eigenLayerStrategies.length()); - status.amounts = new uint256[](eigenLayerStrategies.length()); - - for (uint256 i = 0; i < eigenLayerStrategies.length(); ++i) { - (address strategy, uint48 enabledVaultTime, uint48 disabledVaultTime) = eigenLayerStrategies.atWithTimes(i); - - address collateral = address(IStrategy(strategy).underlyingToken()); - status.collaterals[i] = collateral; - if (!_wasEnabledAt(enabledVaultTime, disabledVaultTime, epochStartTs)) { - continue; - } - - status.amounts[i] = getEigenLayerOperatorStake(operator, collateral); - } - } - - /// @notice Get the amount of tokens delegated to an operator across the allowed strategies. - // @param operator The operator address to get the stake for. - // @param strategies The list of strategies to get the stake for. - // @return tokenAmounts The amount of tokens delegated to the operator for each strategy. - function getEigenLayerOperatorStake(address operator, address collateral) public view returns (uint256 amount) { - uint48 timestamp = Time.timestamp(); - return getEigenLayerOperatorStakeAt(operator, collateral, timestamp); - } - - /// @notice Get the stake of an operator in EigenLayer protocol at a given timestamp. - /// @param operator The operator address to check the stake for. - /// @param collateral The collateral address to check the stake for. - /// @param timestamp The timestamp to check the stake at. - /// @return amount The stake of the operator at the given timestamp, in collateral token. - function getEigenLayerOperatorStakeAt( - address operator, - address collateral, - uint48 timestamp - ) public view returns (uint256 amount) { - if (timestamp > Time.timestamp() || timestamp < START_TIMESTAMP) { - revert InvalidQuery(); - } - - uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); - - // NOTE: Can this be done more gas-efficiently? - IStrategy[] memory strategyMem = new IStrategy[](1); - - for (uint256 i = 0; i < eigenLayerStrategies.length(); i++) { - (address strategy, uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.atWithTimes(i); - - if (collateral != address(IStrategy(strategy).underlyingToken())) { - continue; - } - - if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { - continue; - } - - strategyMem[0] = IStrategy(strategy); - // NOTE: order is preserved i.e., shares[i] corresponds to strategies[i] - uint256[] memory shares = EIGENLAYER_DELEGATION_MANAGER.getOperatorShares(operator, strategyMem); - amount += IStrategy(strategy).sharesToUnderlyingView(shares[0]); - } - - return amount; - } - - /// @notice Get the total stake of all EigenLayer operators at a given epoch for a collateral asset. - /// @param epoch The epoch to check the total stake for. - /// @param collateral The collateral address to check the total stake for. - /// @return totalStake The total stake of all operators at the given epoch, in collateral token. - function getEigenLayerTotalStake(uint48 epoch, address collateral) public view returns (uint256 totalStake) { - uint48 epochStartTs = getEpochStartTs(epoch); - - // for epoch older than SLASHING_WINDOW total stake can be invalidated - // NOTE: not available in EigenLayer yet since slashing is not live - // if ( - // epochStartTs < SLASHING_WINDOW || - // epochStartTs < Time.timestamp() - SLASHING_WINDOW || - // epochStartTs > Time.timestamp() - // ) { - // revert InvalidQuery(); - // } - - for (uint256 i; i < eigenLayerOperators.length(); ++i) { - (address operator, uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.atWithTimes(i); - - // just skip operator if it was added after the target epoch or paused - if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { - continue; - } - - totalStake += getEigenLayerOperatorStake(operator, collateral); - } - } - - // ========= EIGENLAYER AVS FUNCTIONS ========= - - /// @notice Register an EigenLayer layer operator to work in Bolt Protocol. - /// @dev This requires calling the EigenLayer AVS Directory contract to register the operator. - /// EigenLayer internally contains a mapping from `msg.sender` (our AVS contract) to the operator - function registerEigenLayerOperatorToAVS( - address operator, - ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature - ) public { - EIGENLAYER_AVS_DIRECTORY.registerOperatorToAVS(operator, operatorSignature); - } - - function checkIfEigenLayerOperatorRegisteredToAVS( - address operator - ) public view returns (bool registered) { - return EIGENLAYER_AVS_DIRECTORY.avsOperatorStatus(address(this), operator) - == IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED; - } - - /// @notice Deregister an EigenLayer layer operator from working in Bolt Protocol. - /// @dev This requires calling the EigenLayer AVS Directory contract to deregister the operator. - /// EigenLayer internally contains a mapping from `msg.sender` (our AVS contract) to the operator. - function deregisterEigenLayerOperatorFromAVS() public { - EIGENLAYER_AVS_DIRECTORY.deregisterOperatorFromAVS(msg.sender); - } - - /// @notice emits an `AVSMetadataURIUpdated` event indicating the information has updated. - /// @param metadataURI The URI for metadata associated with an avs - function updateEigenLayerAVSMetadataURI( - string calldata metadataURI - ) public onlyOwner { - EIGENLAYER_AVS_DIRECTORY.updateAVSMetadataURI(metadataURI); - } - // ========= HELPER FUNCTIONS ========= /// @notice Check if a map entry was active at a given timestamp.