Skip to content

Commit

Permalink
chore(contracts): remove EL functions from BoltManager, they've been …
Browse files Browse the repository at this point in the history
…moved to middleware
  • Loading branch information
thedevbirb committed Sep 20, 2024
1 parent 6d80967 commit dcce053
Showing 1 changed file with 1 addition and 328 deletions.
329 changes: 1 addition & 328 deletions bolt-contracts/src/contracts/BoltManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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();
Expand All @@ -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 =========
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit dcce053

Please sign in to comment.