From 651b644e990e56aaf421b21638d41d6df4fdce45 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 12 Sep 2024 10:46:23 +0200 Subject: [PATCH 1/5] test(contracts): more on EL integration --- bolt-contracts/src/contracts/BoltManager.sol | 287 +++++++++++++----- .../test/BoltManager.EigenLayer.t.sol | 227 +++++++++++--- 2 files changed, 412 insertions(+), 102 deletions(-) diff --git a/bolt-contracts/src/contracts/BoltManager.sol b/bolt-contracts/src/contracts/BoltManager.sol index 630e12bcd..947f98017 100644 --- a/bolt-contracts/src/contracts/BoltManager.sol +++ b/bolt-contracts/src/contracts/BoltManager.sol @@ -126,8 +126,12 @@ contract BoltManager is IBoltManager, Ownable { SYMBIOTIC_OPERATOR_NET_OPTIN = _symbioticOperatorNetOptIn; SYMBIOTIC_VAULT_REGISTRY = _symbioticVaultRegistry; EIGENLAYER_AVS_DIRECTORY = AVSDirectoryStorage(_eigenlayerAVSDirectory); - EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage(_eigenlayerDelegationManager); - EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage(_eigenlayerStrategyManager); + EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage( + _eigenlayerDelegationManager + ); + EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage( + _eigenlayerStrategyManager + ); } // ========= VIEW FUNCTIONS ========= @@ -140,9 +144,7 @@ contract BoltManager is IBoltManager, Ownable { } /// @notice Get the epoch at a given timestamp. - function getEpochAtTs( - uint48 timestamp - ) public view returns (uint48 epoch) { + function getEpochAtTs(uint48 timestamp) public view returns (uint48 epoch) { return (timestamp - START_TIMESTAMP) / EPOCH_DURATION; } @@ -157,17 +159,27 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to check the authorization for. /// @param pubkeyHash The pubkey hash of the validator to check the authorization for. /// @return True if the operator is authorized, false otherwise. - function isOperatorAuthorizedForValidator(address operator, bytes32 pubkeyHash) public view returns (bool) { + function isOperatorAuthorizedForValidator( + address operator, + bytes32 pubkeyHash + ) public view returns (bool) { if (operator == address(0) || pubkeyHash == bytes32(0)) { revert InvalidQuery(); } - return validators.getValidatorByPubkeyHash(pubkeyHash).authorizedOperator == operator; + return + validators + .getValidatorByPubkeyHash(pubkeyHash) + .authorizedOperator == operator; } /// @notice Get the list of collateral addresses that are whitelisted. /// @return collaterals The list of collateral addresses that are whitelisted. - function getWhitelistedSymbioticCollaterals() public view returns (address[] memory collaterals) { + function getWhitelistedSymbioticCollaterals() + public + view + returns (address[] memory collaterals) + { return whitelistedSymbioticCollaterals.values(); } @@ -182,7 +194,11 @@ contract BoltManager is IBoltManager, Ownable { /// @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) { + function getWhitelistedEigenLayerCollaterals() + public + view + returns (address[] memory strategies) + { return whitelistedEigenLayerCollaterals.values(); } @@ -233,9 +249,7 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Allow an operator to signal opt-in to Bolt Protocol. /// @param operator The operator address to signal opt-in for. - function registerSymbioticOperator( - address operator - ) public { + function registerSymbioticOperator(address operator) public { if (symbioticOperators.contains(operator)) { revert AlreadyRegistered(); } @@ -244,7 +258,12 @@ contract BoltManager is IBoltManager, Ownable { revert NotOperator(); } - if (!IOptInService(SYMBIOTIC_OPERATOR_NET_OPTIN).isOptedIn(operator, BOLT_SYMBIOTIC_NETWORK)) { + if ( + !IOptInService(SYMBIOTIC_OPERATOR_NET_OPTIN).isOptedIn( + operator, + BOLT_SYMBIOTIC_NETWORK + ) + ) { revert OperatorNotOptedIn(); } @@ -274,9 +293,7 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Allow a vault to signal opt-in to Bolt Protocol. /// @param vault The vault address to signal opt-in for. - function registerSymbioticVault( - address vault - ) public { + function registerSymbioticVault(address vault) public { if (symbioticVaults.contains(vault)) { revert AlreadyRegistered(); } @@ -316,10 +333,10 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Check if a vault is currently enabled to work in Bolt Protocol. /// @param vault The vault address to check the enabled status for. /// @return True if the vault is enabled, false otherwise. - function isSymbioticVaultEnabled( - address vault - ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = symbioticVaults.getTimes(vault); + function isSymbioticVaultEnabled(address vault) public view returns (bool) { + (uint48 enabledTime, uint48 disabledTime) = symbioticVaults.getTimes( + vault + ); return enabledTime != 0 && disabledTime == 0; } @@ -329,7 +346,9 @@ contract BoltManager is IBoltManager, Ownable { function isSymbioticOperatorEnabled( address operator ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes( + operator + ); return enabledTime != 0 && disabledTime == 0; } @@ -356,14 +375,22 @@ contract BoltManager is IBoltManager, Ownable { } uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); + IBoltValidators.Validator memory validator = validators + .getValidatorByPubkeyHash(pubkeyHash); + + if (!validator.exists) { + revert IBoltValidators.ValidatorDoesNotExist(); + } + address operator = validator.authorizedOperator; status.pubkeyHash = pubkeyHash; status.active = validator.exists; status.operator = operator; - (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes( + operator + ); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { return status; } @@ -372,15 +399,29 @@ contract BoltManager is IBoltManager, Ownable { status.amounts = new uint256[](symbioticVaults.length()); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - (address vault, uint48 enabledVaultTime, uint48 disabledVaultTime) = symbioticVaults.atWithTimes(i); + ( + address vault, + uint48 enabledVaultTime, + uint48 disabledVaultTime + ) = symbioticVaults.atWithTimes(i); address collateral = IVault(vault).collateral(); status.collaterals[i] = collateral; - if (!_wasEnabledAt(enabledVaultTime, disabledVaultTime, epochStartTs)) { + if ( + !_wasEnabledAt( + enabledVaultTime, + disabledVaultTime, + epochStartTs + ) + ) { continue; } - status.amounts[i] = getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); + status.amounts[i] = getSymbioticOperatorStakeAt( + operator, + collateral, + epochStartTs + ); } } @@ -388,7 +429,10 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to check the stake for. /// @param collateral The collateral address to check the stake for. /// @return amount The stake of the operator at the current timestamp, in collateral token. - function getSymbioticOperatorStake(address operator, address collateral) public view returns (uint256 amount) { + function getSymbioticOperatorStake( + address operator, + address collateral + ) public view returns (uint256 amount) { uint48 timestamp = Time.timestamp(); return getSymbioticOperatorStakeAt(operator, collateral, timestamp); } @@ -410,7 +454,11 @@ contract BoltManager is IBoltManager, Ownable { uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - (address vault, uint48 enabledTime, uint48 disabledTime) = symbioticVaults.atWithTimes(i); + ( + address vault, + uint48 enabledTime, + uint48 disabledTime + ) = symbioticVaults.atWithTimes(i); if (collateral != IVault(vault).collateral()) { continue; @@ -440,26 +488,38 @@ contract BoltManager is IBoltManager, Ownable { /// @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 getSymbioticTotalStake(uint48 epoch, address collateral) public view returns (uint256 totalStake) { + function getSymbioticTotalStake( + uint48 epoch, + address collateral + ) public view returns (uint256 totalStake) { uint48 epochStartTs = getEpochStartTs(epoch); // for epoch older than SLASHING_WINDOW total stake can be invalidated if ( - epochStartTs < SLASHING_WINDOW || epochStartTs < Time.timestamp() - SLASHING_WINDOW - || epochStartTs > Time.timestamp() + epochStartTs < SLASHING_WINDOW || + epochStartTs < Time.timestamp() - SLASHING_WINDOW || + epochStartTs > Time.timestamp() ) { revert InvalidQuery(); } for (uint256 i; i < symbioticOperators.length(); ++i) { - (address operator, uint48 enabledTime, uint48 disabledTime) = symbioticOperators.atWithTimes(i); + ( + address operator, + uint48 enabledTime, + uint48 disabledTime + ) = symbioticOperators.atWithTimes(i); // just skip operator if it was added after the target epoch or paused if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { continue; } - totalStake += getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); + totalStake += getSymbioticOperatorStakeAt( + operator, + collateral, + epochStartTs + ); } } @@ -468,14 +528,23 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to slash. /// @param collateral The collateral address to slash. /// @param amount The amount of collateral to slash. - function slash(uint48 timestamp, address operator, address collateral, uint256 amount) public onlyOwner { + function slash( + uint48 timestamp, + address operator, + address collateral, + uint256 amount + ) public onlyOwner { // TODO: remove onlyOwner modifier and gate the slashing logic behind the BoltChallenger // fault proof mechanism to allow for permissionless slashing. uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - (address vault, uint48 enabledTime, uint48 disabledTime) = symbioticVaults.atWithTimes(i); + ( + address vault, + uint48 enabledTime, + uint48 disabledTime + ) = symbioticVaults.atWithTimes(i); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { continue; @@ -485,18 +554,31 @@ contract BoltManager is IBoltManager, Ownable { continue; } - uint256 operatorStake = getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); + uint256 operatorStake = getSymbioticOperatorStakeAt( + operator, + collateral, + epochStartTs + ); if (amount > operatorStake) { revert SlashAmountTooHigh(); } - uint256 vaultStake = IBaseDelegator(IVault(vault).delegator()).stakeAt( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, epochStartTs, new bytes(0) - ); + uint256 vaultStake = IBaseDelegator(IVault(vault).delegator()) + .stakeAt( + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), + operator, + epochStartTs, + new bytes(0) + ); // Slash the vault pro-rata. - _slashSymbioticVault(epochStartTs, vault, operator, (amount * vaultStake) / operatorStake); + _slashSymbioticVault( + epochStartTs, + vault, + operator, + (amount * vaultStake) / operatorStake + ); } } @@ -504,9 +586,7 @@ contract BoltManager is IBoltManager, Ownable { /// @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 { + function registerEigenLayerOperator(address operator) public { if (eigenLayerOperators.contains(operator)) { revert AlreadyRegistered(); } @@ -543,18 +623,24 @@ contract BoltManager is IBoltManager, Ownable { eigenLayerOperators.enable(msg.sender); } - function registerEigenLayerStrategy( - address strategy - ) public { + function registerEigenLayerStrategy(address strategy) public { if (eigenLayerStrategies.contains(strategy)) { revert AlreadyRegistered(); } - if (!EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit(IStrategy(strategy))) { + if ( + !EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit( + IStrategy(strategy) + ) + ) { revert StrategyNotAllowed(); } - if (!isEigenLayerCollateralWhitelisted(address(IStrategy(strategy).underlyingToken()))) { + if ( + !isEigenLayerCollateralWhitelisted( + address(IStrategy(strategy).underlyingToken()) + ) + ) { revert CollateralNotWhitelisted(); } @@ -586,7 +672,8 @@ contract BoltManager is IBoltManager, Ownable { function isEigenLayerStrategyEnabled( address strategy ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.getTimes(strategy); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies + .getTimes(strategy); return enabledTime != 0 && disabledTime == 0; } @@ -596,7 +683,8 @@ contract BoltManager is IBoltManager, Ownable { function isEigenLayerOperatorEnabled( address operator ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators + .getTimes(operator); return enabledTime != 0 && disabledTime == 0; } @@ -623,14 +711,21 @@ contract BoltManager is IBoltManager, Ownable { } uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); + IBoltValidators.Validator memory validator = validators + .getValidatorByPubkeyHash(pubkeyHash); + + if (!validator.exists) { + revert IBoltValidators.ValidatorDoesNotExist(); + } + address operator = validator.authorizedOperator; status.pubkeyHash = pubkeyHash; status.active = validator.exists; status.operator = operator; - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators + .getTimes(operator); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { return status; } @@ -639,15 +734,28 @@ contract BoltManager is IBoltManager, Ownable { status.amounts = new uint256[](eigenLayerStrategies.length()); for (uint256 i = 0; i < eigenLayerStrategies.length(); ++i) { - (address strategy, uint48 enabledVaultTime, uint48 disabledVaultTime) = eigenLayerStrategies.atWithTimes(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)) { + if ( + !_wasEnabledAt( + enabledVaultTime, + disabledVaultTime, + epochStartTs + ) + ) { continue; } - status.amounts[i] = getEigenLayerOperatorStake(operator, collateral); + status.amounts[i] = getEigenLayerOperatorStake( + operator, + collateral + ); } } @@ -655,7 +763,10 @@ contract BoltManager is IBoltManager, Ownable { // @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) { + function getEigenLayerOperatorStake( + address operator, + address collateral + ) public view returns (uint256 amount) { uint48 timestamp = Time.timestamp(); return getEigenLayerOperatorStakeAt(operator, collateral, timestamp); } @@ -680,7 +791,11 @@ contract BoltManager is IBoltManager, Ownable { IStrategy[] memory strategyMem = new IStrategy[](1); for (uint256 i = 0; i < eigenLayerStrategies.length(); i++) { - (address strategy, uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.atWithTimes(i); + ( + address strategy, + uint48 enabledTime, + uint48 disabledTime + ) = eigenLayerStrategies.atWithTimes(i); if (collateral != address(IStrategy(strategy).underlyingToken())) { continue; @@ -692,7 +807,8 @@ contract BoltManager is IBoltManager, Ownable { 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); + uint256[] memory shares = EIGENLAYER_DELEGATION_MANAGER + .getOperatorShares(operator, strategyMem); amount += IStrategy(strategy).sharesToUnderlyingView(shares[0]); } @@ -703,7 +819,10 @@ contract BoltManager is IBoltManager, Ownable { /// @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) { + 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 @@ -717,7 +836,11 @@ contract BoltManager is IBoltManager, Ownable { // } for (uint256 i; i < eigenLayerOperators.length(); ++i) { - (address operator, uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.atWithTimes(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)) { @@ -737,14 +860,20 @@ contract BoltManager is IBoltManager, Ownable { address operator, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature ) public { - EIGENLAYER_AVS_DIRECTORY.registerOperatorToAVS(operator, operatorSignature); + 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; + return + EIGENLAYER_AVS_DIRECTORY.avsOperatorStatus( + address(this), + operator + ) == IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED; } /// @notice Deregister an EigenLayer layer operator from working in Bolt Protocol. @@ -769,23 +898,45 @@ contract BoltManager is IBoltManager, Ownable { /// @param disabledTime The disabled time of the map entry. /// @param timestamp The timestamp to check the map entry status at. /// @return True if the map entry was active at the given timestamp, false otherwise. - function _wasEnabledAt(uint48 enabledTime, uint48 disabledTime, uint48 timestamp) private pure returns (bool) { - return enabledTime != 0 && enabledTime <= timestamp && (disabledTime == 0 || disabledTime >= timestamp); + function _wasEnabledAt( + uint48 enabledTime, + uint48 disabledTime, + uint48 timestamp + ) private pure returns (bool) { + return + enabledTime != 0 && + enabledTime <= timestamp && + (disabledTime == 0 || disabledTime >= timestamp); } /// @notice Slash an operator for a given amount of collateral. /// @param timestamp The timestamp of the slash event. /// @param operator The operator address to slash. /// @param amount The amount of collateral to slash. - function _slashSymbioticVault(uint48 timestamp, address vault, address operator, uint256 amount) private { + function _slashSymbioticVault( + uint48 timestamp, + address vault, + address operator, + uint256 amount + ) private { address slasher = IVault(vault).slasher(); uint256 slasherType = IEntity(slasher).TYPE(); if (slasherType == INSTANT_SLASHER_TYPE) { - ISlasher(slasher).slash(BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, amount, timestamp, new bytes(0)); + ISlasher(slasher).slash( + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), + operator, + amount, + timestamp, + new bytes(0) + ); } else if (slasherType == VETO_SLASHER_TYPE) { IVetoSlasher(slasher).requestSlash( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, amount, timestamp, new bytes(0) + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), + operator, + amount, + timestamp, + new bytes(0) ); } else { revert UnknownSlasherType(); diff --git a/bolt-contracts/test/BoltManager.EigenLayer.t.sol b/bolt-contracts/test/BoltManager.EigenLayer.t.sol index ee1751dfd..440c9980b 100644 --- a/bolt-contracts/test/BoltManager.EigenLayer.t.sol +++ b/bolt-contracts/test/BoltManager.EigenLayer.t.sol @@ -5,6 +5,8 @@ import {Test, console} from "forge-std/Test.sol"; import {BoltValidators} from "../src/contracts/BoltValidators.sol"; import {BoltManager} from "../src/contracts/BoltManager.sol"; +import {IBoltValidators} from "../src/interfaces/IBoltValidators.sol"; +import {IBoltManager} from "../src/interfaces/IBoltManager.sol"; import {AVSDirectoryStorage} from "@eigenlayer/src/contracts/core/AVSDirectoryStorage.sol"; import {DelegationManagerStorage} from "@eigenlayer/src/contracts/core/DelegationManagerStorage.sol"; @@ -17,12 +19,17 @@ import {EigenLayerDeployer} from "../test/fixtures/EigenLayerDeployer.f.sol"; import {BLS12381} from "../src/lib/bls/BLS12381.sol"; contract BoltManagerEigenLayerTest is Test { + using BLS12381 for BLS12381.G1Point; + + uint48 public constant EPOCH_DURATION = 1 days; + BoltValidators public validators; BoltManager public manager; EigenLayerDeployer public eigenLayerDeployer; address staker = makeAddr("staker"); address validator = makeAddr("validator"); + BLS12381.G1Point validatorPubkey = BLS12381.generatorG1(); address operator; uint256 operatorSk; @@ -52,11 +59,22 @@ contract BoltManagerEigenLayerTest is Test { ); } - function _eigenLayerOptInRoutine() internal { + function _adminRoutine() internal { // PART 0: Admin setup -- Collateral whitelist vm.startPrank(admin); - manager.addWhitelistedEigenLayerCollateral(address(eigenLayerDeployer.weth())); + manager.addWhitelistedEigenLayerCollateral( + address(eigenLayerDeployer.weth()) + ); vm.stopPrank(); + assertEq(manager.getWhitelistedEigenLayerCollaterals().length, 1); + assertEq( + manager.getWhitelistedEigenLayerCollaterals()[0], + address(eigenLayerDeployer.weth()) + ); + } + + function _eigenLayerOptInRoutine() internal { + _adminRoutine(); // PART 1: External EigenLayer opt-in to BOLT AVS @@ -64,21 +82,38 @@ contract BoltManagerEigenLayerTest is Test { // After this, I get back some shares that I can use at a later time for withdrawal vm.startPrank(staker); - eigenLayerDeployer.weth().approve(address(eigenLayerDeployer.strategyManager()), 1 ether); - uint256 shares = eigenLayerDeployer.strategyManager().depositIntoStrategy( - eigenLayerDeployer.wethStrat(), eigenLayerDeployer.weth(), 1 ether + eigenLayerDeployer.weth().approve( + address(eigenLayerDeployer.strategyManager()), + 1 ether ); + uint256 shares = eigenLayerDeployer + .strategyManager() + .depositIntoStrategy( + eigenLayerDeployer.wethStrat(), + eigenLayerDeployer.weth(), + 1 ether + ); vm.stopPrank(); - assertEq(eigenLayerDeployer.wethStrat().sharesToUnderlyingView(shares), 1 ether); + assertEq( + eigenLayerDeployer.wethStrat().sharesToUnderlyingView(shares), + 1 ether + ); // 2. As a Operator, I register myself into EigenLayer using DelegationManager.registerAsOperator. // Note that this function doesn’t require specifying anything related to the service I’m going to provide. // However, a parameter describes who can delegate to me whether it can be anyone or a subset of stakers. - IDelegationManager.OperatorDetails memory operatorDetails = - IDelegationManager.OperatorDetails(address(0), address(0), 0); + IDelegationManager.OperatorDetails + memory operatorDetails = IDelegationManager.OperatorDetails( + address(0), + address(0), + 0 + ); vm.startPrank(operator); - eigenLayerDeployer.delegationManager().registerAsOperator(operatorDetails, "https://boltprotocol.xyz"); + eigenLayerDeployer.delegationManager().registerAsOperator( + operatorDetails, + "https://boltprotocol.xyz" + ); vm.stopPrank(); // 3. As a staker, I can start delegating funds to these operators using @@ -86,12 +121,22 @@ contract BoltManagerEigenLayerTest is Test { // to delegate my funds // NOTE: this signature is not used since the operator allows funds delegated from anyone - ISignatureUtils.SignatureWithExpiry memory signature = ISignatureUtils.SignatureWithExpiry(bytes(""), 0); - console.logAddress(eigenLayerDeployer.delegationManager().delegatedTo(staker)); + ISignatureUtils.SignatureWithExpiry memory signature = ISignatureUtils + .SignatureWithExpiry(bytes(""), 0); + console.logAddress( + eigenLayerDeployer.delegationManager().delegatedTo(staker) + ); vm.startPrank(staker); - eigenLayerDeployer.delegationManager().delegateTo(operator, signature, bytes32(0)); + eigenLayerDeployer.delegationManager().delegateTo( + operator, + signature, + bytes32(0) + ); vm.stopPrank(); - assertEq(eigenLayerDeployer.delegationManager().delegatedTo(staker), operator); + assertEq( + eigenLayerDeployer.delegationManager().delegatedTo(staker), + operator + ); // 4. As an AVS developer I create an entrypoint contract. // Upon deploying the contract it is required to make a call to EL’s @@ -114,59 +159,173 @@ contract BoltManagerEigenLayerTest is Test { // the operator is considered REGISTERED in a mapping avsOperatorStatus[msg.sender][operator]. // Calculate the digest hash - bytes32 operatorRegistrationDigestHash = eigenLayerDeployer.avsDirectory() + bytes32 operatorRegistrationDigestHash = eigenLayerDeployer + .avsDirectory() .calculateOperatorAVSRegistrationDigestHash({ - operator: operator, - avs: address(manager), - salt: bytes32(0), - expiry: UINT256_MAX - }); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(operatorSk, operatorRegistrationDigestHash); + operator: operator, + avs: address(manager), + salt: bytes32(0), + expiry: UINT256_MAX + }); + (uint8 v, bytes32 r, bytes32 s) = vm.sign( + operatorSk, + operatorRegistrationDigestHash + ); bytes memory operatorRawSignature = abi.encodePacked(r, s, v); - ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = - ISignatureUtils.SignatureWithSaltAndExpiry(operatorRawSignature, bytes32(0), UINT256_MAX); + ISignatureUtils.SignatureWithSaltAndExpiry + memory operatorSignature = ISignatureUtils + .SignatureWithSaltAndExpiry( + operatorRawSignature, + bytes32(0), + UINT256_MAX + ); vm.expectEmit(true, true, true, true); emit IAVSDirectory.OperatorAVSRegistrationStatusUpdated( - operator, address(manager), IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED + operator, + address(manager), + IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED ); manager.registerEigenLayerOperatorToAVS(operator, operatorSignature); - assertEq(manager.checkIfEigenLayerOperatorRegisteredToAVS(operator), true); + assertEq( + manager.checkIfEigenLayerOperatorRegisteredToAVS(operator), + true + ); // PART 2: Validator and proposer opt into BOLT manager // // 1. --- Register Validator in BoltValidators --- // pubkeys aren't checked, any point will be fine - BLS12381.G1Point memory pubkey = BLS12381.generatorG1(); + validatorPubkey = BLS12381.generatorG1(); vm.prank(validator); - validators.registerValidatorUnsafe(pubkey, staker, operator); - assertEq(validators.getValidatorByPubkey(pubkey).exists, true); - assertEq(validators.getValidatorByPubkey(pubkey).authorizedOperator, operator); - assertEq(validators.getValidatorByPubkey(pubkey).authorizedCollateralProvider, staker); + validators.registerValidatorUnsafe(validatorPubkey, staker, operator); + assertEq(validators.getValidatorByPubkey(validatorPubkey).exists, true); + assertEq( + validators.getValidatorByPubkey(validatorPubkey).authorizedOperator, + operator + ); + assertEq( + validators + .getValidatorByPubkey(validatorPubkey) + .authorizedCollateralProvider, + staker + ); // 2. --- Operator and strategy registration into BoltManager (middleware) --- manager.registerEigenLayerOperator(operator); assertEq(manager.isEigenLayerOperatorEnabled(operator), true); - manager.registerEigenLayerStrategy(address(eigenLayerDeployer.wethStrat())); - assertEq(manager.isEigenLayerStrategyEnabled(address(eigenLayerDeployer.wethStrat())), true); + manager.registerEigenLayerStrategy( + address(eigenLayerDeployer.wethStrat()) + ); + assertEq( + manager.isEigenLayerStrategyEnabled( + address(eigenLayerDeployer.wethStrat()) + ), + true + ); } function test_deregisterEigenLayerOperatorFromAVS() public { _eigenLayerOptInRoutine(); vm.prank(operator); manager.deregisterEigenLayerOperatorFromAVS(); - assertEq(manager.checkIfEigenLayerOperatorRegisteredToAVS(operator), false); + assertEq( + manager.checkIfEigenLayerOperatorRegisteredToAVS(operator), + false + ); } function test_getEigenLayerOperatorStake() public { _eigenLayerOptInRoutine(); - uint256 amount = manager.getEigenLayerOperatorStake(operator, address(eigenLayerDeployer.weth())); - uint256 totalStake = manager.getEigenLayerTotalStake(2, address(eigenLayerDeployer.weth())); + uint256 amount = manager.getEigenLayerOperatorStake( + operator, + address(eigenLayerDeployer.weth()) + ); + uint256 totalStake = manager.getEigenLayerTotalStake( + 2, + address(eigenLayerDeployer.weth()) + ); assertEq(amount, 1 ether); assertEq(totalStake, 1 ether); } + + function test_getEigenLayerProposerStatus() public { + _eigenLayerOptInRoutine(); + + bytes32 pubkeyHash = _pubkeyHash(validatorPubkey); + + BoltManager.ProposerStatus memory status = manager + .getEigenLayerProposerStatus(pubkeyHash); + assertEq(status.pubkeyHash, pubkeyHash); + assertEq(status.operator, operator); + assertEq(status.active, true); + assertEq(status.collaterals.length, 1); + assertEq(status.amounts.length, 1); + assertEq(status.collaterals[0], address(eigenLayerDeployer.weth())); + assertEq(status.amounts[0], 1 ether); + } + + function testProposersLookaheadStatus() public { + // This also opts in the operator which is needed + _eigenLayerOptInRoutine(); + bytes32[] memory pubkeyHashes = new bytes32[](10); + + // register 10 proposers with random pubkeys + for (uint256 i = 0; i < 10; i++) { + BLS12381.G1Point memory pubkey = BLS12381.generatorG1(); + pubkey.x[0] = pubkey.x[0] + i + 2; + pubkey.y[0] = pubkey.y[0] + i + 2; + + pubkeyHashes[i] = _pubkeyHash(pubkey); + validators.registerValidatorUnsafe(pubkey, staker, operator); + } + + BoltManager.ProposerStatus[] memory statuses = manager + .getEigenLayerProposersStatus(pubkeyHashes); + assertEq(statuses.length, 10); + } + + function testGetNonExistentProposerStatus() public { + _eigenLayerOptInRoutine(); + + bytes32 pubkeyHash = bytes32(uint256(1)); + + vm.expectRevert(IBoltValidators.ValidatorDoesNotExist.selector); + manager.getEigenLayerProposerStatus(pubkeyHash); + } + + function testGetWhitelistedCollaterals() public { + _adminRoutine(); + address[] memory collaterals = manager + .getWhitelistedEigenLayerCollaterals(); + assertEq(collaterals.length, 1); + assertEq(collaterals[0], address(eigenLayerDeployer.weth())); + } + + function testNonWhitelistedCollateral() public { + _adminRoutine(); + vm.startPrank(admin); + manager.removeWhitelistedEigenLayerCollateral( + address(eigenLayerDeployer.weth()) + ); + vm.stopPrank(); + + address strat = address(eigenLayerDeployer.wethStrat()); + vm.startPrank(admin); + vm.expectRevert(IBoltManager.CollateralNotWhitelisted.selector); + manager.registerEigenLayerStrategy(strat); + vm.stopPrank(); + } + + /// @notice Compute the hash of a BLS public key + function _pubkeyHash( + BLS12381.G1Point memory _pubkey + ) internal pure returns (bytes32) { + uint256[2] memory compressedPubKey = _pubkey.compress(); + return keccak256(abi.encodePacked(compressedPubKey)); + } } From cf13b00b7285c976c47cabfbca83bf3b4b0a8336 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 12 Sep 2024 10:46:44 +0200 Subject: [PATCH 2/5] chore(contracts): forge fmt --- bolt-contracts/src/contracts/BoltManager.sol | 277 +++++------------- .../test/BoltManager.EigenLayer.t.sol | 145 +++------ 2 files changed, 103 insertions(+), 319 deletions(-) diff --git a/bolt-contracts/src/contracts/BoltManager.sol b/bolt-contracts/src/contracts/BoltManager.sol index 947f98017..3f1c7e0a6 100644 --- a/bolt-contracts/src/contracts/BoltManager.sol +++ b/bolt-contracts/src/contracts/BoltManager.sol @@ -126,12 +126,8 @@ contract BoltManager is IBoltManager, Ownable { SYMBIOTIC_OPERATOR_NET_OPTIN = _symbioticOperatorNetOptIn; SYMBIOTIC_VAULT_REGISTRY = _symbioticVaultRegistry; EIGENLAYER_AVS_DIRECTORY = AVSDirectoryStorage(_eigenlayerAVSDirectory); - EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage( - _eigenlayerDelegationManager - ); - EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage( - _eigenlayerStrategyManager - ); + EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage(_eigenlayerDelegationManager); + EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage(_eigenlayerStrategyManager); } // ========= VIEW FUNCTIONS ========= @@ -144,7 +140,9 @@ contract BoltManager is IBoltManager, Ownable { } /// @notice Get the epoch at a given timestamp. - function getEpochAtTs(uint48 timestamp) public view returns (uint48 epoch) { + function getEpochAtTs( + uint48 timestamp + ) public view returns (uint48 epoch) { return (timestamp - START_TIMESTAMP) / EPOCH_DURATION; } @@ -159,27 +157,17 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to check the authorization for. /// @param pubkeyHash The pubkey hash of the validator to check the authorization for. /// @return True if the operator is authorized, false otherwise. - function isOperatorAuthorizedForValidator( - address operator, - bytes32 pubkeyHash - ) public view returns (bool) { + function isOperatorAuthorizedForValidator(address operator, bytes32 pubkeyHash) public view returns (bool) { if (operator == address(0) || pubkeyHash == bytes32(0)) { revert InvalidQuery(); } - return - validators - .getValidatorByPubkeyHash(pubkeyHash) - .authorizedOperator == operator; + return validators.getValidatorByPubkeyHash(pubkeyHash).authorizedOperator == operator; } /// @notice Get the list of collateral addresses that are whitelisted. /// @return collaterals The list of collateral addresses that are whitelisted. - function getWhitelistedSymbioticCollaterals() - public - view - returns (address[] memory collaterals) - { + function getWhitelistedSymbioticCollaterals() public view returns (address[] memory collaterals) { return whitelistedSymbioticCollaterals.values(); } @@ -194,11 +182,7 @@ contract BoltManager is IBoltManager, Ownable { /// @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) - { + function getWhitelistedEigenLayerCollaterals() public view returns (address[] memory strategies) { return whitelistedEigenLayerCollaterals.values(); } @@ -249,7 +233,9 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Allow an operator to signal opt-in to Bolt Protocol. /// @param operator The operator address to signal opt-in for. - function registerSymbioticOperator(address operator) public { + function registerSymbioticOperator( + address operator + ) public { if (symbioticOperators.contains(operator)) { revert AlreadyRegistered(); } @@ -258,12 +244,7 @@ contract BoltManager is IBoltManager, Ownable { revert NotOperator(); } - if ( - !IOptInService(SYMBIOTIC_OPERATOR_NET_OPTIN).isOptedIn( - operator, - BOLT_SYMBIOTIC_NETWORK - ) - ) { + if (!IOptInService(SYMBIOTIC_OPERATOR_NET_OPTIN).isOptedIn(operator, BOLT_SYMBIOTIC_NETWORK)) { revert OperatorNotOptedIn(); } @@ -293,7 +274,9 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Allow a vault to signal opt-in to Bolt Protocol. /// @param vault The vault address to signal opt-in for. - function registerSymbioticVault(address vault) public { + function registerSymbioticVault( + address vault + ) public { if (symbioticVaults.contains(vault)) { revert AlreadyRegistered(); } @@ -333,10 +316,10 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Check if a vault is currently enabled to work in Bolt Protocol. /// @param vault The vault address to check the enabled status for. /// @return True if the vault is enabled, false otherwise. - function isSymbioticVaultEnabled(address vault) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = symbioticVaults.getTimes( - vault - ); + function isSymbioticVaultEnabled( + address vault + ) public view returns (bool) { + (uint48 enabledTime, uint48 disabledTime) = symbioticVaults.getTimes(vault); return enabledTime != 0 && disabledTime == 0; } @@ -346,9 +329,7 @@ contract BoltManager is IBoltManager, Ownable { function isSymbioticOperatorEnabled( address operator ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes( - operator - ); + (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes(operator); return enabledTime != 0 && disabledTime == 0; } @@ -375,8 +356,7 @@ contract BoltManager is IBoltManager, Ownable { } uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators - .getValidatorByPubkeyHash(pubkeyHash); + IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); if (!validator.exists) { revert IBoltValidators.ValidatorDoesNotExist(); @@ -388,9 +368,7 @@ contract BoltManager is IBoltManager, Ownable { status.active = validator.exists; status.operator = operator; - (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes( - operator - ); + (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes(operator); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { return status; } @@ -399,29 +377,15 @@ contract BoltManager is IBoltManager, Ownable { status.amounts = new uint256[](symbioticVaults.length()); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - ( - address vault, - uint48 enabledVaultTime, - uint48 disabledVaultTime - ) = symbioticVaults.atWithTimes(i); + (address vault, uint48 enabledVaultTime, uint48 disabledVaultTime) = symbioticVaults.atWithTimes(i); address collateral = IVault(vault).collateral(); status.collaterals[i] = collateral; - if ( - !_wasEnabledAt( - enabledVaultTime, - disabledVaultTime, - epochStartTs - ) - ) { + if (!_wasEnabledAt(enabledVaultTime, disabledVaultTime, epochStartTs)) { continue; } - status.amounts[i] = getSymbioticOperatorStakeAt( - operator, - collateral, - epochStartTs - ); + status.amounts[i] = getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); } } @@ -429,10 +393,7 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to check the stake for. /// @param collateral The collateral address to check the stake for. /// @return amount The stake of the operator at the current timestamp, in collateral token. - function getSymbioticOperatorStake( - address operator, - address collateral - ) public view returns (uint256 amount) { + function getSymbioticOperatorStake(address operator, address collateral) public view returns (uint256 amount) { uint48 timestamp = Time.timestamp(); return getSymbioticOperatorStakeAt(operator, collateral, timestamp); } @@ -454,11 +415,7 @@ contract BoltManager is IBoltManager, Ownable { uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - ( - address vault, - uint48 enabledTime, - uint48 disabledTime - ) = symbioticVaults.atWithTimes(i); + (address vault, uint48 enabledTime, uint48 disabledTime) = symbioticVaults.atWithTimes(i); if (collateral != IVault(vault).collateral()) { continue; @@ -488,38 +445,26 @@ contract BoltManager is IBoltManager, Ownable { /// @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 getSymbioticTotalStake( - uint48 epoch, - address collateral - ) public view returns (uint256 totalStake) { + function getSymbioticTotalStake(uint48 epoch, address collateral) public view returns (uint256 totalStake) { uint48 epochStartTs = getEpochStartTs(epoch); // for epoch older than SLASHING_WINDOW total stake can be invalidated if ( - epochStartTs < SLASHING_WINDOW || - epochStartTs < Time.timestamp() - SLASHING_WINDOW || - epochStartTs > Time.timestamp() + epochStartTs < SLASHING_WINDOW || epochStartTs < Time.timestamp() - SLASHING_WINDOW + || epochStartTs > Time.timestamp() ) { revert InvalidQuery(); } for (uint256 i; i < symbioticOperators.length(); ++i) { - ( - address operator, - uint48 enabledTime, - uint48 disabledTime - ) = symbioticOperators.atWithTimes(i); + (address operator, uint48 enabledTime, uint48 disabledTime) = symbioticOperators.atWithTimes(i); // just skip operator if it was added after the target epoch or paused if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { continue; } - totalStake += getSymbioticOperatorStakeAt( - operator, - collateral, - epochStartTs - ); + totalStake += getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); } } @@ -528,23 +473,14 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to slash. /// @param collateral The collateral address to slash. /// @param amount The amount of collateral to slash. - function slash( - uint48 timestamp, - address operator, - address collateral, - uint256 amount - ) public onlyOwner { + function slash(uint48 timestamp, address operator, address collateral, uint256 amount) public onlyOwner { // TODO: remove onlyOwner modifier and gate the slashing logic behind the BoltChallenger // fault proof mechanism to allow for permissionless slashing. uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - ( - address vault, - uint48 enabledTime, - uint48 disabledTime - ) = symbioticVaults.atWithTimes(i); + (address vault, uint48 enabledTime, uint48 disabledTime) = symbioticVaults.atWithTimes(i); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { continue; @@ -554,31 +490,18 @@ contract BoltManager is IBoltManager, Ownable { continue; } - uint256 operatorStake = getSymbioticOperatorStakeAt( - operator, - collateral, - epochStartTs - ); + uint256 operatorStake = getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); if (amount > operatorStake) { revert SlashAmountTooHigh(); } - uint256 vaultStake = IBaseDelegator(IVault(vault).delegator()) - .stakeAt( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), - operator, - epochStartTs, - new bytes(0) - ); + uint256 vaultStake = IBaseDelegator(IVault(vault).delegator()).stakeAt( + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, epochStartTs, new bytes(0) + ); // Slash the vault pro-rata. - _slashSymbioticVault( - epochStartTs, - vault, - operator, - (amount * vaultStake) / operatorStake - ); + _slashSymbioticVault(epochStartTs, vault, operator, (amount * vaultStake) / operatorStake); } } @@ -586,7 +509,9 @@ contract BoltManager is IBoltManager, Ownable { /// @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 { + function registerEigenLayerOperator( + address operator + ) public { if (eigenLayerOperators.contains(operator)) { revert AlreadyRegistered(); } @@ -623,24 +548,18 @@ contract BoltManager is IBoltManager, Ownable { eigenLayerOperators.enable(msg.sender); } - function registerEigenLayerStrategy(address strategy) public { + function registerEigenLayerStrategy( + address strategy + ) public { if (eigenLayerStrategies.contains(strategy)) { revert AlreadyRegistered(); } - if ( - !EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit( - IStrategy(strategy) - ) - ) { + if (!EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit(IStrategy(strategy))) { revert StrategyNotAllowed(); } - if ( - !isEigenLayerCollateralWhitelisted( - address(IStrategy(strategy).underlyingToken()) - ) - ) { + if (!isEigenLayerCollateralWhitelisted(address(IStrategy(strategy).underlyingToken()))) { revert CollateralNotWhitelisted(); } @@ -672,8 +591,7 @@ contract BoltManager is IBoltManager, Ownable { function isEigenLayerStrategyEnabled( address strategy ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies - .getTimes(strategy); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.getTimes(strategy); return enabledTime != 0 && disabledTime == 0; } @@ -683,8 +601,7 @@ contract BoltManager is IBoltManager, Ownable { function isEigenLayerOperatorEnabled( address operator ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators - .getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); return enabledTime != 0 && disabledTime == 0; } @@ -711,8 +628,7 @@ contract BoltManager is IBoltManager, Ownable { } uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators - .getValidatorByPubkeyHash(pubkeyHash); + IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); if (!validator.exists) { revert IBoltValidators.ValidatorDoesNotExist(); @@ -724,8 +640,7 @@ contract BoltManager is IBoltManager, Ownable { status.active = validator.exists; status.operator = operator; - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators - .getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { return status; } @@ -734,28 +649,15 @@ contract BoltManager is IBoltManager, Ownable { status.amounts = new uint256[](eigenLayerStrategies.length()); for (uint256 i = 0; i < eigenLayerStrategies.length(); ++i) { - ( - address strategy, - uint48 enabledVaultTime, - uint48 disabledVaultTime - ) = eigenLayerStrategies.atWithTimes(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 - ) - ) { + if (!_wasEnabledAt(enabledVaultTime, disabledVaultTime, epochStartTs)) { continue; } - status.amounts[i] = getEigenLayerOperatorStake( - operator, - collateral - ); + status.amounts[i] = getEigenLayerOperatorStake(operator, collateral); } } @@ -763,10 +665,7 @@ contract BoltManager is IBoltManager, Ownable { // @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) { + function getEigenLayerOperatorStake(address operator, address collateral) public view returns (uint256 amount) { uint48 timestamp = Time.timestamp(); return getEigenLayerOperatorStakeAt(operator, collateral, timestamp); } @@ -791,11 +690,7 @@ contract BoltManager is IBoltManager, Ownable { IStrategy[] memory strategyMem = new IStrategy[](1); for (uint256 i = 0; i < eigenLayerStrategies.length(); i++) { - ( - address strategy, - uint48 enabledTime, - uint48 disabledTime - ) = eigenLayerStrategies.atWithTimes(i); + (address strategy, uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.atWithTimes(i); if (collateral != address(IStrategy(strategy).underlyingToken())) { continue; @@ -807,8 +702,7 @@ contract BoltManager is IBoltManager, Ownable { 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); + uint256[] memory shares = EIGENLAYER_DELEGATION_MANAGER.getOperatorShares(operator, strategyMem); amount += IStrategy(strategy).sharesToUnderlyingView(shares[0]); } @@ -819,10 +713,7 @@ contract BoltManager is IBoltManager, Ownable { /// @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) { + 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 @@ -836,11 +727,7 @@ contract BoltManager is IBoltManager, Ownable { // } for (uint256 i; i < eigenLayerOperators.length(); ++i) { - ( - address operator, - uint48 enabledTime, - uint48 disabledTime - ) = eigenLayerOperators.atWithTimes(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)) { @@ -860,20 +747,14 @@ contract BoltManager is IBoltManager, Ownable { address operator, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature ) public { - EIGENLAYER_AVS_DIRECTORY.registerOperatorToAVS( - operator, - operatorSignature - ); + 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; + return EIGENLAYER_AVS_DIRECTORY.avsOperatorStatus(address(this), operator) + == IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED; } /// @notice Deregister an EigenLayer layer operator from working in Bolt Protocol. @@ -898,45 +779,23 @@ contract BoltManager is IBoltManager, Ownable { /// @param disabledTime The disabled time of the map entry. /// @param timestamp The timestamp to check the map entry status at. /// @return True if the map entry was active at the given timestamp, false otherwise. - function _wasEnabledAt( - uint48 enabledTime, - uint48 disabledTime, - uint48 timestamp - ) private pure returns (bool) { - return - enabledTime != 0 && - enabledTime <= timestamp && - (disabledTime == 0 || disabledTime >= timestamp); + function _wasEnabledAt(uint48 enabledTime, uint48 disabledTime, uint48 timestamp) private pure returns (bool) { + return enabledTime != 0 && enabledTime <= timestamp && (disabledTime == 0 || disabledTime >= timestamp); } /// @notice Slash an operator for a given amount of collateral. /// @param timestamp The timestamp of the slash event. /// @param operator The operator address to slash. /// @param amount The amount of collateral to slash. - function _slashSymbioticVault( - uint48 timestamp, - address vault, - address operator, - uint256 amount - ) private { + function _slashSymbioticVault(uint48 timestamp, address vault, address operator, uint256 amount) private { address slasher = IVault(vault).slasher(); uint256 slasherType = IEntity(slasher).TYPE(); if (slasherType == INSTANT_SLASHER_TYPE) { - ISlasher(slasher).slash( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), - operator, - amount, - timestamp, - new bytes(0) - ); + ISlasher(slasher).slash(BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, amount, timestamp, new bytes(0)); } else if (slasherType == VETO_SLASHER_TYPE) { IVetoSlasher(slasher).requestSlash( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), - operator, - amount, - timestamp, - new bytes(0) + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, amount, timestamp, new bytes(0) ); } else { revert UnknownSlasherType(); diff --git a/bolt-contracts/test/BoltManager.EigenLayer.t.sol b/bolt-contracts/test/BoltManager.EigenLayer.t.sol index 440c9980b..da0613b44 100644 --- a/bolt-contracts/test/BoltManager.EigenLayer.t.sol +++ b/bolt-contracts/test/BoltManager.EigenLayer.t.sol @@ -62,15 +62,10 @@ contract BoltManagerEigenLayerTest is Test { function _adminRoutine() internal { // PART 0: Admin setup -- Collateral whitelist vm.startPrank(admin); - manager.addWhitelistedEigenLayerCollateral( - address(eigenLayerDeployer.weth()) - ); + manager.addWhitelistedEigenLayerCollateral(address(eigenLayerDeployer.weth())); vm.stopPrank(); assertEq(manager.getWhitelistedEigenLayerCollaterals().length, 1); - assertEq( - manager.getWhitelistedEigenLayerCollaterals()[0], - address(eigenLayerDeployer.weth()) - ); + assertEq(manager.getWhitelistedEigenLayerCollaterals()[0], address(eigenLayerDeployer.weth())); } function _eigenLayerOptInRoutine() internal { @@ -82,38 +77,21 @@ contract BoltManagerEigenLayerTest is Test { // After this, I get back some shares that I can use at a later time for withdrawal vm.startPrank(staker); - eigenLayerDeployer.weth().approve( - address(eigenLayerDeployer.strategyManager()), - 1 ether + eigenLayerDeployer.weth().approve(address(eigenLayerDeployer.strategyManager()), 1 ether); + uint256 shares = eigenLayerDeployer.strategyManager().depositIntoStrategy( + eigenLayerDeployer.wethStrat(), eigenLayerDeployer.weth(), 1 ether ); - uint256 shares = eigenLayerDeployer - .strategyManager() - .depositIntoStrategy( - eigenLayerDeployer.wethStrat(), - eigenLayerDeployer.weth(), - 1 ether - ); vm.stopPrank(); - assertEq( - eigenLayerDeployer.wethStrat().sharesToUnderlyingView(shares), - 1 ether - ); + assertEq(eigenLayerDeployer.wethStrat().sharesToUnderlyingView(shares), 1 ether); // 2. As a Operator, I register myself into EigenLayer using DelegationManager.registerAsOperator. // Note that this function doesn’t require specifying anything related to the service I’m going to provide. // However, a parameter describes who can delegate to me whether it can be anyone or a subset of stakers. - IDelegationManager.OperatorDetails - memory operatorDetails = IDelegationManager.OperatorDetails( - address(0), - address(0), - 0 - ); + IDelegationManager.OperatorDetails memory operatorDetails = + IDelegationManager.OperatorDetails(address(0), address(0), 0); vm.startPrank(operator); - eigenLayerDeployer.delegationManager().registerAsOperator( - operatorDetails, - "https://boltprotocol.xyz" - ); + eigenLayerDeployer.delegationManager().registerAsOperator(operatorDetails, "https://boltprotocol.xyz"); vm.stopPrank(); // 3. As a staker, I can start delegating funds to these operators using @@ -121,22 +99,12 @@ contract BoltManagerEigenLayerTest is Test { // to delegate my funds // NOTE: this signature is not used since the operator allows funds delegated from anyone - ISignatureUtils.SignatureWithExpiry memory signature = ISignatureUtils - .SignatureWithExpiry(bytes(""), 0); - console.logAddress( - eigenLayerDeployer.delegationManager().delegatedTo(staker) - ); + ISignatureUtils.SignatureWithExpiry memory signature = ISignatureUtils.SignatureWithExpiry(bytes(""), 0); + console.logAddress(eigenLayerDeployer.delegationManager().delegatedTo(staker)); vm.startPrank(staker); - eigenLayerDeployer.delegationManager().delegateTo( - operator, - signature, - bytes32(0) - ); + eigenLayerDeployer.delegationManager().delegateTo(operator, signature, bytes32(0)); vm.stopPrank(); - assertEq( - eigenLayerDeployer.delegationManager().delegatedTo(staker), - operator - ); + assertEq(eigenLayerDeployer.delegationManager().delegatedTo(staker), operator); // 4. As an AVS developer I create an entrypoint contract. // Upon deploying the contract it is required to make a call to EL’s @@ -159,37 +127,23 @@ contract BoltManagerEigenLayerTest is Test { // the operator is considered REGISTERED in a mapping avsOperatorStatus[msg.sender][operator]. // Calculate the digest hash - bytes32 operatorRegistrationDigestHash = eigenLayerDeployer - .avsDirectory() + bytes32 operatorRegistrationDigestHash = eigenLayerDeployer.avsDirectory() .calculateOperatorAVSRegistrationDigestHash({ - operator: operator, - avs: address(manager), - salt: bytes32(0), - expiry: UINT256_MAX - }); - (uint8 v, bytes32 r, bytes32 s) = vm.sign( - operatorSk, - operatorRegistrationDigestHash - ); + operator: operator, + avs: address(manager), + salt: bytes32(0), + expiry: UINT256_MAX + }); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(operatorSk, operatorRegistrationDigestHash); bytes memory operatorRawSignature = abi.encodePacked(r, s, v); - ISignatureUtils.SignatureWithSaltAndExpiry - memory operatorSignature = ISignatureUtils - .SignatureWithSaltAndExpiry( - operatorRawSignature, - bytes32(0), - UINT256_MAX - ); + ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature = + ISignatureUtils.SignatureWithSaltAndExpiry(operatorRawSignature, bytes32(0), UINT256_MAX); vm.expectEmit(true, true, true, true); emit IAVSDirectory.OperatorAVSRegistrationStatusUpdated( - operator, - address(manager), - IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED + operator, address(manager), IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED ); manager.registerEigenLayerOperatorToAVS(operator, operatorSignature); - assertEq( - manager.checkIfEigenLayerOperatorRegisteredToAVS(operator), - true - ); + assertEq(manager.checkIfEigenLayerOperatorRegisteredToAVS(operator), true); // PART 2: Validator and proposer opt into BOLT manager // @@ -201,54 +155,30 @@ contract BoltManagerEigenLayerTest is Test { vm.prank(validator); validators.registerValidatorUnsafe(validatorPubkey, staker, operator); assertEq(validators.getValidatorByPubkey(validatorPubkey).exists, true); - assertEq( - validators.getValidatorByPubkey(validatorPubkey).authorizedOperator, - operator - ); - assertEq( - validators - .getValidatorByPubkey(validatorPubkey) - .authorizedCollateralProvider, - staker - ); + assertEq(validators.getValidatorByPubkey(validatorPubkey).authorizedOperator, operator); + assertEq(validators.getValidatorByPubkey(validatorPubkey).authorizedCollateralProvider, staker); // 2. --- Operator and strategy registration into BoltManager (middleware) --- manager.registerEigenLayerOperator(operator); assertEq(manager.isEigenLayerOperatorEnabled(operator), true); - manager.registerEigenLayerStrategy( - address(eigenLayerDeployer.wethStrat()) - ); - assertEq( - manager.isEigenLayerStrategyEnabled( - address(eigenLayerDeployer.wethStrat()) - ), - true - ); + manager.registerEigenLayerStrategy(address(eigenLayerDeployer.wethStrat())); + assertEq(manager.isEigenLayerStrategyEnabled(address(eigenLayerDeployer.wethStrat())), true); } function test_deregisterEigenLayerOperatorFromAVS() public { _eigenLayerOptInRoutine(); vm.prank(operator); manager.deregisterEigenLayerOperatorFromAVS(); - assertEq( - manager.checkIfEigenLayerOperatorRegisteredToAVS(operator), - false - ); + assertEq(manager.checkIfEigenLayerOperatorRegisteredToAVS(operator), false); } function test_getEigenLayerOperatorStake() public { _eigenLayerOptInRoutine(); - uint256 amount = manager.getEigenLayerOperatorStake( - operator, - address(eigenLayerDeployer.weth()) - ); - uint256 totalStake = manager.getEigenLayerTotalStake( - 2, - address(eigenLayerDeployer.weth()) - ); + uint256 amount = manager.getEigenLayerOperatorStake(operator, address(eigenLayerDeployer.weth())); + uint256 totalStake = manager.getEigenLayerTotalStake(2, address(eigenLayerDeployer.weth())); assertEq(amount, 1 ether); assertEq(totalStake, 1 ether); } @@ -258,8 +188,7 @@ contract BoltManagerEigenLayerTest is Test { bytes32 pubkeyHash = _pubkeyHash(validatorPubkey); - BoltManager.ProposerStatus memory status = manager - .getEigenLayerProposerStatus(pubkeyHash); + BoltManager.ProposerStatus memory status = manager.getEigenLayerProposerStatus(pubkeyHash); assertEq(status.pubkeyHash, pubkeyHash); assertEq(status.operator, operator); assertEq(status.active, true); @@ -284,8 +213,7 @@ contract BoltManagerEigenLayerTest is Test { validators.registerValidatorUnsafe(pubkey, staker, operator); } - BoltManager.ProposerStatus[] memory statuses = manager - .getEigenLayerProposersStatus(pubkeyHashes); + BoltManager.ProposerStatus[] memory statuses = manager.getEigenLayerProposersStatus(pubkeyHashes); assertEq(statuses.length, 10); } @@ -300,8 +228,7 @@ contract BoltManagerEigenLayerTest is Test { function testGetWhitelistedCollaterals() public { _adminRoutine(); - address[] memory collaterals = manager - .getWhitelistedEigenLayerCollaterals(); + address[] memory collaterals = manager.getWhitelistedEigenLayerCollaterals(); assertEq(collaterals.length, 1); assertEq(collaterals[0], address(eigenLayerDeployer.weth())); } @@ -309,9 +236,7 @@ contract BoltManagerEigenLayerTest is Test { function testNonWhitelistedCollateral() public { _adminRoutine(); vm.startPrank(admin); - manager.removeWhitelistedEigenLayerCollateral( - address(eigenLayerDeployer.weth()) - ); + manager.removeWhitelistedEigenLayerCollateral(address(eigenLayerDeployer.weth())); vm.stopPrank(); address strat = address(eigenLayerDeployer.wethStrat()); From 4eaf8c624346ddfb707b95e9f87119ad633a77f3 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 12 Sep 2024 10:48:43 +0200 Subject: [PATCH 3/5] chore(contracts): test file rename --- .../test/{BoltManager.t.sol => BoltManager.Symbiotic.t.sol} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename bolt-contracts/test/{BoltManager.t.sol => BoltManager.Symbiotic.t.sol} (100%) diff --git a/bolt-contracts/test/BoltManager.t.sol b/bolt-contracts/test/BoltManager.Symbiotic.t.sol similarity index 100% rename from bolt-contracts/test/BoltManager.t.sol rename to bolt-contracts/test/BoltManager.Symbiotic.t.sol From 72aeb339b6d4f5dc25a8c09838a1757908b132a9 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Fri, 13 Sep 2024 08:53:00 +0200 Subject: [PATCH 4/5] chore(contracts): remove duplicate revert --- bolt-contracts/src/contracts/BoltManager.sol | 285 ++++++++++++++----- 1 file changed, 209 insertions(+), 76 deletions(-) diff --git a/bolt-contracts/src/contracts/BoltManager.sol b/bolt-contracts/src/contracts/BoltManager.sol index 3f1c7e0a6..028c2c687 100644 --- a/bolt-contracts/src/contracts/BoltManager.sol +++ b/bolt-contracts/src/contracts/BoltManager.sol @@ -126,8 +126,12 @@ contract BoltManager is IBoltManager, Ownable { SYMBIOTIC_OPERATOR_NET_OPTIN = _symbioticOperatorNetOptIn; SYMBIOTIC_VAULT_REGISTRY = _symbioticVaultRegistry; EIGENLAYER_AVS_DIRECTORY = AVSDirectoryStorage(_eigenlayerAVSDirectory); - EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage(_eigenlayerDelegationManager); - EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage(_eigenlayerStrategyManager); + EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage( + _eigenlayerDelegationManager + ); + EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage( + _eigenlayerStrategyManager + ); } // ========= VIEW FUNCTIONS ========= @@ -140,9 +144,7 @@ contract BoltManager is IBoltManager, Ownable { } /// @notice Get the epoch at a given timestamp. - function getEpochAtTs( - uint48 timestamp - ) public view returns (uint48 epoch) { + function getEpochAtTs(uint48 timestamp) public view returns (uint48 epoch) { return (timestamp - START_TIMESTAMP) / EPOCH_DURATION; } @@ -157,17 +159,27 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to check the authorization for. /// @param pubkeyHash The pubkey hash of the validator to check the authorization for. /// @return True if the operator is authorized, false otherwise. - function isOperatorAuthorizedForValidator(address operator, bytes32 pubkeyHash) public view returns (bool) { + function isOperatorAuthorizedForValidator( + address operator, + bytes32 pubkeyHash + ) public view returns (bool) { if (operator == address(0) || pubkeyHash == bytes32(0)) { revert InvalidQuery(); } - return validators.getValidatorByPubkeyHash(pubkeyHash).authorizedOperator == operator; + return + validators + .getValidatorByPubkeyHash(pubkeyHash) + .authorizedOperator == operator; } /// @notice Get the list of collateral addresses that are whitelisted. /// @return collaterals The list of collateral addresses that are whitelisted. - function getWhitelistedSymbioticCollaterals() public view returns (address[] memory collaterals) { + function getWhitelistedSymbioticCollaterals() + public + view + returns (address[] memory collaterals) + { return whitelistedSymbioticCollaterals.values(); } @@ -182,7 +194,11 @@ contract BoltManager is IBoltManager, Ownable { /// @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) { + function getWhitelistedEigenLayerCollaterals() + public + view + returns (address[] memory strategies) + { return whitelistedEigenLayerCollaterals.values(); } @@ -233,9 +249,7 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Allow an operator to signal opt-in to Bolt Protocol. /// @param operator The operator address to signal opt-in for. - function registerSymbioticOperator( - address operator - ) public { + function registerSymbioticOperator(address operator) public { if (symbioticOperators.contains(operator)) { revert AlreadyRegistered(); } @@ -244,7 +258,12 @@ contract BoltManager is IBoltManager, Ownable { revert NotOperator(); } - if (!IOptInService(SYMBIOTIC_OPERATOR_NET_OPTIN).isOptedIn(operator, BOLT_SYMBIOTIC_NETWORK)) { + if ( + !IOptInService(SYMBIOTIC_OPERATOR_NET_OPTIN).isOptedIn( + operator, + BOLT_SYMBIOTIC_NETWORK + ) + ) { revert OperatorNotOptedIn(); } @@ -274,9 +293,7 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Allow a vault to signal opt-in to Bolt Protocol. /// @param vault The vault address to signal opt-in for. - function registerSymbioticVault( - address vault - ) public { + function registerSymbioticVault(address vault) public { if (symbioticVaults.contains(vault)) { revert AlreadyRegistered(); } @@ -316,10 +333,10 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Check if a vault is currently enabled to work in Bolt Protocol. /// @param vault The vault address to check the enabled status for. /// @return True if the vault is enabled, false otherwise. - function isSymbioticVaultEnabled( - address vault - ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = symbioticVaults.getTimes(vault); + function isSymbioticVaultEnabled(address vault) public view returns (bool) { + (uint48 enabledTime, uint48 disabledTime) = symbioticVaults.getTimes( + vault + ); return enabledTime != 0 && disabledTime == 0; } @@ -329,7 +346,9 @@ contract BoltManager is IBoltManager, Ownable { function isSymbioticOperatorEnabled( address operator ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes( + operator + ); return enabledTime != 0 && disabledTime == 0; } @@ -356,11 +375,8 @@ contract BoltManager is IBoltManager, Ownable { } uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); - - if (!validator.exists) { - revert IBoltValidators.ValidatorDoesNotExist(); - } + IBoltValidators.Validator memory validator = validators + .getValidatorByPubkeyHash(pubkeyHash); address operator = validator.authorizedOperator; @@ -368,7 +384,9 @@ contract BoltManager is IBoltManager, Ownable { status.active = validator.exists; status.operator = operator; - (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes( + operator + ); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { return status; } @@ -377,15 +395,29 @@ contract BoltManager is IBoltManager, Ownable { status.amounts = new uint256[](symbioticVaults.length()); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - (address vault, uint48 enabledVaultTime, uint48 disabledVaultTime) = symbioticVaults.atWithTimes(i); + ( + address vault, + uint48 enabledVaultTime, + uint48 disabledVaultTime + ) = symbioticVaults.atWithTimes(i); address collateral = IVault(vault).collateral(); status.collaterals[i] = collateral; - if (!_wasEnabledAt(enabledVaultTime, disabledVaultTime, epochStartTs)) { + if ( + !_wasEnabledAt( + enabledVaultTime, + disabledVaultTime, + epochStartTs + ) + ) { continue; } - status.amounts[i] = getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); + status.amounts[i] = getSymbioticOperatorStakeAt( + operator, + collateral, + epochStartTs + ); } } @@ -393,7 +425,10 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to check the stake for. /// @param collateral The collateral address to check the stake for. /// @return amount The stake of the operator at the current timestamp, in collateral token. - function getSymbioticOperatorStake(address operator, address collateral) public view returns (uint256 amount) { + function getSymbioticOperatorStake( + address operator, + address collateral + ) public view returns (uint256 amount) { uint48 timestamp = Time.timestamp(); return getSymbioticOperatorStakeAt(operator, collateral, timestamp); } @@ -415,7 +450,11 @@ contract BoltManager is IBoltManager, Ownable { uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - (address vault, uint48 enabledTime, uint48 disabledTime) = symbioticVaults.atWithTimes(i); + ( + address vault, + uint48 enabledTime, + uint48 disabledTime + ) = symbioticVaults.atWithTimes(i); if (collateral != IVault(vault).collateral()) { continue; @@ -445,26 +484,38 @@ contract BoltManager is IBoltManager, Ownable { /// @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 getSymbioticTotalStake(uint48 epoch, address collateral) public view returns (uint256 totalStake) { + function getSymbioticTotalStake( + uint48 epoch, + address collateral + ) public view returns (uint256 totalStake) { uint48 epochStartTs = getEpochStartTs(epoch); // for epoch older than SLASHING_WINDOW total stake can be invalidated if ( - epochStartTs < SLASHING_WINDOW || epochStartTs < Time.timestamp() - SLASHING_WINDOW - || epochStartTs > Time.timestamp() + epochStartTs < SLASHING_WINDOW || + epochStartTs < Time.timestamp() - SLASHING_WINDOW || + epochStartTs > Time.timestamp() ) { revert InvalidQuery(); } for (uint256 i; i < symbioticOperators.length(); ++i) { - (address operator, uint48 enabledTime, uint48 disabledTime) = symbioticOperators.atWithTimes(i); + ( + address operator, + uint48 enabledTime, + uint48 disabledTime + ) = symbioticOperators.atWithTimes(i); // just skip operator if it was added after the target epoch or paused if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { continue; } - totalStake += getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); + totalStake += getSymbioticOperatorStakeAt( + operator, + collateral, + epochStartTs + ); } } @@ -473,14 +524,23 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to slash. /// @param collateral The collateral address to slash. /// @param amount The amount of collateral to slash. - function slash(uint48 timestamp, address operator, address collateral, uint256 amount) public onlyOwner { + function slash( + uint48 timestamp, + address operator, + address collateral, + uint256 amount + ) public onlyOwner { // TODO: remove onlyOwner modifier and gate the slashing logic behind the BoltChallenger // fault proof mechanism to allow for permissionless slashing. uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - (address vault, uint48 enabledTime, uint48 disabledTime) = symbioticVaults.atWithTimes(i); + ( + address vault, + uint48 enabledTime, + uint48 disabledTime + ) = symbioticVaults.atWithTimes(i); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { continue; @@ -490,18 +550,31 @@ contract BoltManager is IBoltManager, Ownable { continue; } - uint256 operatorStake = getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); + uint256 operatorStake = getSymbioticOperatorStakeAt( + operator, + collateral, + epochStartTs + ); if (amount > operatorStake) { revert SlashAmountTooHigh(); } - uint256 vaultStake = IBaseDelegator(IVault(vault).delegator()).stakeAt( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, epochStartTs, new bytes(0) - ); + uint256 vaultStake = IBaseDelegator(IVault(vault).delegator()) + .stakeAt( + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), + operator, + epochStartTs, + new bytes(0) + ); // Slash the vault pro-rata. - _slashSymbioticVault(epochStartTs, vault, operator, (amount * vaultStake) / operatorStake); + _slashSymbioticVault( + epochStartTs, + vault, + operator, + (amount * vaultStake) / operatorStake + ); } } @@ -509,9 +582,7 @@ contract BoltManager is IBoltManager, Ownable { /// @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 { + function registerEigenLayerOperator(address operator) public { if (eigenLayerOperators.contains(operator)) { revert AlreadyRegistered(); } @@ -548,18 +619,24 @@ contract BoltManager is IBoltManager, Ownable { eigenLayerOperators.enable(msg.sender); } - function registerEigenLayerStrategy( - address strategy - ) public { + function registerEigenLayerStrategy(address strategy) public { if (eigenLayerStrategies.contains(strategy)) { revert AlreadyRegistered(); } - if (!EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit(IStrategy(strategy))) { + if ( + !EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit( + IStrategy(strategy) + ) + ) { revert StrategyNotAllowed(); } - if (!isEigenLayerCollateralWhitelisted(address(IStrategy(strategy).underlyingToken()))) { + if ( + !isEigenLayerCollateralWhitelisted( + address(IStrategy(strategy).underlyingToken()) + ) + ) { revert CollateralNotWhitelisted(); } @@ -591,7 +668,8 @@ contract BoltManager is IBoltManager, Ownable { function isEigenLayerStrategyEnabled( address strategy ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.getTimes(strategy); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies + .getTimes(strategy); return enabledTime != 0 && disabledTime == 0; } @@ -601,7 +679,8 @@ contract BoltManager is IBoltManager, Ownable { function isEigenLayerOperatorEnabled( address operator ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators + .getTimes(operator); return enabledTime != 0 && disabledTime == 0; } @@ -628,11 +707,8 @@ contract BoltManager is IBoltManager, Ownable { } uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); - - if (!validator.exists) { - revert IBoltValidators.ValidatorDoesNotExist(); - } + IBoltValidators.Validator memory validator = validators + .getValidatorByPubkeyHash(pubkeyHash); address operator = validator.authorizedOperator; @@ -640,7 +716,8 @@ contract BoltManager is IBoltManager, Ownable { status.active = validator.exists; status.operator = operator; - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators + .getTimes(operator); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { return status; } @@ -649,15 +726,28 @@ contract BoltManager is IBoltManager, Ownable { status.amounts = new uint256[](eigenLayerStrategies.length()); for (uint256 i = 0; i < eigenLayerStrategies.length(); ++i) { - (address strategy, uint48 enabledVaultTime, uint48 disabledVaultTime) = eigenLayerStrategies.atWithTimes(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)) { + if ( + !_wasEnabledAt( + enabledVaultTime, + disabledVaultTime, + epochStartTs + ) + ) { continue; } - status.amounts[i] = getEigenLayerOperatorStake(operator, collateral); + status.amounts[i] = getEigenLayerOperatorStake( + operator, + collateral + ); } } @@ -665,7 +755,10 @@ contract BoltManager is IBoltManager, Ownable { // @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) { + function getEigenLayerOperatorStake( + address operator, + address collateral + ) public view returns (uint256 amount) { uint48 timestamp = Time.timestamp(); return getEigenLayerOperatorStakeAt(operator, collateral, timestamp); } @@ -690,7 +783,11 @@ contract BoltManager is IBoltManager, Ownable { IStrategy[] memory strategyMem = new IStrategy[](1); for (uint256 i = 0; i < eigenLayerStrategies.length(); i++) { - (address strategy, uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.atWithTimes(i); + ( + address strategy, + uint48 enabledTime, + uint48 disabledTime + ) = eigenLayerStrategies.atWithTimes(i); if (collateral != address(IStrategy(strategy).underlyingToken())) { continue; @@ -702,7 +799,8 @@ contract BoltManager is IBoltManager, Ownable { 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); + uint256[] memory shares = EIGENLAYER_DELEGATION_MANAGER + .getOperatorShares(operator, strategyMem); amount += IStrategy(strategy).sharesToUnderlyingView(shares[0]); } @@ -713,7 +811,10 @@ contract BoltManager is IBoltManager, Ownable { /// @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) { + 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 @@ -727,7 +828,11 @@ contract BoltManager is IBoltManager, Ownable { // } for (uint256 i; i < eigenLayerOperators.length(); ++i) { - (address operator, uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.atWithTimes(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)) { @@ -747,14 +852,20 @@ contract BoltManager is IBoltManager, Ownable { address operator, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature ) public { - EIGENLAYER_AVS_DIRECTORY.registerOperatorToAVS(operator, operatorSignature); + 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; + return + EIGENLAYER_AVS_DIRECTORY.avsOperatorStatus( + address(this), + operator + ) == IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED; } /// @notice Deregister an EigenLayer layer operator from working in Bolt Protocol. @@ -779,23 +890,45 @@ contract BoltManager is IBoltManager, Ownable { /// @param disabledTime The disabled time of the map entry. /// @param timestamp The timestamp to check the map entry status at. /// @return True if the map entry was active at the given timestamp, false otherwise. - function _wasEnabledAt(uint48 enabledTime, uint48 disabledTime, uint48 timestamp) private pure returns (bool) { - return enabledTime != 0 && enabledTime <= timestamp && (disabledTime == 0 || disabledTime >= timestamp); + function _wasEnabledAt( + uint48 enabledTime, + uint48 disabledTime, + uint48 timestamp + ) private pure returns (bool) { + return + enabledTime != 0 && + enabledTime <= timestamp && + (disabledTime == 0 || disabledTime >= timestamp); } /// @notice Slash an operator for a given amount of collateral. /// @param timestamp The timestamp of the slash event. /// @param operator The operator address to slash. /// @param amount The amount of collateral to slash. - function _slashSymbioticVault(uint48 timestamp, address vault, address operator, uint256 amount) private { + function _slashSymbioticVault( + uint48 timestamp, + address vault, + address operator, + uint256 amount + ) private { address slasher = IVault(vault).slasher(); uint256 slasherType = IEntity(slasher).TYPE(); if (slasherType == INSTANT_SLASHER_TYPE) { - ISlasher(slasher).slash(BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, amount, timestamp, new bytes(0)); + ISlasher(slasher).slash( + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), + operator, + amount, + timestamp, + new bytes(0) + ); } else if (slasherType == VETO_SLASHER_TYPE) { IVetoSlasher(slasher).requestSlash( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, amount, timestamp, new bytes(0) + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), + operator, + amount, + timestamp, + new bytes(0) ); } else { revert UnknownSlasherType(); From ac3a61552d0ad2ff8021cbf445d777cb374fe253 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Fri, 13 Sep 2024 09:03:47 +0200 Subject: [PATCH 5/5] chore(contracts): forge fmt --- bolt-contracts/src/contracts/BoltManager.sol | 277 +++++-------------- 1 file changed, 68 insertions(+), 209 deletions(-) diff --git a/bolt-contracts/src/contracts/BoltManager.sol b/bolt-contracts/src/contracts/BoltManager.sol index 028c2c687..b3585dd56 100644 --- a/bolt-contracts/src/contracts/BoltManager.sol +++ b/bolt-contracts/src/contracts/BoltManager.sol @@ -126,12 +126,8 @@ contract BoltManager is IBoltManager, Ownable { SYMBIOTIC_OPERATOR_NET_OPTIN = _symbioticOperatorNetOptIn; SYMBIOTIC_VAULT_REGISTRY = _symbioticVaultRegistry; EIGENLAYER_AVS_DIRECTORY = AVSDirectoryStorage(_eigenlayerAVSDirectory); - EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage( - _eigenlayerDelegationManager - ); - EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage( - _eigenlayerStrategyManager - ); + EIGENLAYER_DELEGATION_MANAGER = DelegationManagerStorage(_eigenlayerDelegationManager); + EIGENLAYER_STRATEGY_MANAGER = StrategyManagerStorage(_eigenlayerStrategyManager); } // ========= VIEW FUNCTIONS ========= @@ -144,7 +140,9 @@ contract BoltManager is IBoltManager, Ownable { } /// @notice Get the epoch at a given timestamp. - function getEpochAtTs(uint48 timestamp) public view returns (uint48 epoch) { + function getEpochAtTs( + uint48 timestamp + ) public view returns (uint48 epoch) { return (timestamp - START_TIMESTAMP) / EPOCH_DURATION; } @@ -159,27 +157,17 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to check the authorization for. /// @param pubkeyHash The pubkey hash of the validator to check the authorization for. /// @return True if the operator is authorized, false otherwise. - function isOperatorAuthorizedForValidator( - address operator, - bytes32 pubkeyHash - ) public view returns (bool) { + function isOperatorAuthorizedForValidator(address operator, bytes32 pubkeyHash) public view returns (bool) { if (operator == address(0) || pubkeyHash == bytes32(0)) { revert InvalidQuery(); } - return - validators - .getValidatorByPubkeyHash(pubkeyHash) - .authorizedOperator == operator; + return validators.getValidatorByPubkeyHash(pubkeyHash).authorizedOperator == operator; } /// @notice Get the list of collateral addresses that are whitelisted. /// @return collaterals The list of collateral addresses that are whitelisted. - function getWhitelistedSymbioticCollaterals() - public - view - returns (address[] memory collaterals) - { + function getWhitelistedSymbioticCollaterals() public view returns (address[] memory collaterals) { return whitelistedSymbioticCollaterals.values(); } @@ -194,11 +182,7 @@ contract BoltManager is IBoltManager, Ownable { /// @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) - { + function getWhitelistedEigenLayerCollaterals() public view returns (address[] memory strategies) { return whitelistedEigenLayerCollaterals.values(); } @@ -249,7 +233,9 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Allow an operator to signal opt-in to Bolt Protocol. /// @param operator The operator address to signal opt-in for. - function registerSymbioticOperator(address operator) public { + function registerSymbioticOperator( + address operator + ) public { if (symbioticOperators.contains(operator)) { revert AlreadyRegistered(); } @@ -258,12 +244,7 @@ contract BoltManager is IBoltManager, Ownable { revert NotOperator(); } - if ( - !IOptInService(SYMBIOTIC_OPERATOR_NET_OPTIN).isOptedIn( - operator, - BOLT_SYMBIOTIC_NETWORK - ) - ) { + if (!IOptInService(SYMBIOTIC_OPERATOR_NET_OPTIN).isOptedIn(operator, BOLT_SYMBIOTIC_NETWORK)) { revert OperatorNotOptedIn(); } @@ -293,7 +274,9 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Allow a vault to signal opt-in to Bolt Protocol. /// @param vault The vault address to signal opt-in for. - function registerSymbioticVault(address vault) public { + function registerSymbioticVault( + address vault + ) public { if (symbioticVaults.contains(vault)) { revert AlreadyRegistered(); } @@ -333,10 +316,10 @@ contract BoltManager is IBoltManager, Ownable { /// @notice Check if a vault is currently enabled to work in Bolt Protocol. /// @param vault The vault address to check the enabled status for. /// @return True if the vault is enabled, false otherwise. - function isSymbioticVaultEnabled(address vault) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = symbioticVaults.getTimes( - vault - ); + function isSymbioticVaultEnabled( + address vault + ) public view returns (bool) { + (uint48 enabledTime, uint48 disabledTime) = symbioticVaults.getTimes(vault); return enabledTime != 0 && disabledTime == 0; } @@ -346,9 +329,7 @@ contract BoltManager is IBoltManager, Ownable { function isSymbioticOperatorEnabled( address operator ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes( - operator - ); + (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes(operator); return enabledTime != 0 && disabledTime == 0; } @@ -375,8 +356,7 @@ contract BoltManager is IBoltManager, Ownable { } uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators - .getValidatorByPubkeyHash(pubkeyHash); + IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); address operator = validator.authorizedOperator; @@ -384,9 +364,7 @@ contract BoltManager is IBoltManager, Ownable { status.active = validator.exists; status.operator = operator; - (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes( - operator - ); + (uint48 enabledTime, uint48 disabledTime) = symbioticOperators.getTimes(operator); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { return status; } @@ -395,29 +373,15 @@ contract BoltManager is IBoltManager, Ownable { status.amounts = new uint256[](symbioticVaults.length()); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - ( - address vault, - uint48 enabledVaultTime, - uint48 disabledVaultTime - ) = symbioticVaults.atWithTimes(i); + (address vault, uint48 enabledVaultTime, uint48 disabledVaultTime) = symbioticVaults.atWithTimes(i); address collateral = IVault(vault).collateral(); status.collaterals[i] = collateral; - if ( - !_wasEnabledAt( - enabledVaultTime, - disabledVaultTime, - epochStartTs - ) - ) { + if (!_wasEnabledAt(enabledVaultTime, disabledVaultTime, epochStartTs)) { continue; } - status.amounts[i] = getSymbioticOperatorStakeAt( - operator, - collateral, - epochStartTs - ); + status.amounts[i] = getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); } } @@ -425,10 +389,7 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to check the stake for. /// @param collateral The collateral address to check the stake for. /// @return amount The stake of the operator at the current timestamp, in collateral token. - function getSymbioticOperatorStake( - address operator, - address collateral - ) public view returns (uint256 amount) { + function getSymbioticOperatorStake(address operator, address collateral) public view returns (uint256 amount) { uint48 timestamp = Time.timestamp(); return getSymbioticOperatorStakeAt(operator, collateral, timestamp); } @@ -450,11 +411,7 @@ contract BoltManager is IBoltManager, Ownable { uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - ( - address vault, - uint48 enabledTime, - uint48 disabledTime - ) = symbioticVaults.atWithTimes(i); + (address vault, uint48 enabledTime, uint48 disabledTime) = symbioticVaults.atWithTimes(i); if (collateral != IVault(vault).collateral()) { continue; @@ -484,38 +441,26 @@ contract BoltManager is IBoltManager, Ownable { /// @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 getSymbioticTotalStake( - uint48 epoch, - address collateral - ) public view returns (uint256 totalStake) { + function getSymbioticTotalStake(uint48 epoch, address collateral) public view returns (uint256 totalStake) { uint48 epochStartTs = getEpochStartTs(epoch); // for epoch older than SLASHING_WINDOW total stake can be invalidated if ( - epochStartTs < SLASHING_WINDOW || - epochStartTs < Time.timestamp() - SLASHING_WINDOW || - epochStartTs > Time.timestamp() + epochStartTs < SLASHING_WINDOW || epochStartTs < Time.timestamp() - SLASHING_WINDOW + || epochStartTs > Time.timestamp() ) { revert InvalidQuery(); } for (uint256 i; i < symbioticOperators.length(); ++i) { - ( - address operator, - uint48 enabledTime, - uint48 disabledTime - ) = symbioticOperators.atWithTimes(i); + (address operator, uint48 enabledTime, uint48 disabledTime) = symbioticOperators.atWithTimes(i); // just skip operator if it was added after the target epoch or paused if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { continue; } - totalStake += getSymbioticOperatorStakeAt( - operator, - collateral, - epochStartTs - ); + totalStake += getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); } } @@ -524,23 +469,14 @@ contract BoltManager is IBoltManager, Ownable { /// @param operator The operator address to slash. /// @param collateral The collateral address to slash. /// @param amount The amount of collateral to slash. - function slash( - uint48 timestamp, - address operator, - address collateral, - uint256 amount - ) public onlyOwner { + function slash(uint48 timestamp, address operator, address collateral, uint256 amount) public onlyOwner { // TODO: remove onlyOwner modifier and gate the slashing logic behind the BoltChallenger // fault proof mechanism to allow for permissionless slashing. uint48 epochStartTs = getEpochStartTs(getEpochAtTs(timestamp)); for (uint256 i = 0; i < symbioticVaults.length(); ++i) { - ( - address vault, - uint48 enabledTime, - uint48 disabledTime - ) = symbioticVaults.atWithTimes(i); + (address vault, uint48 enabledTime, uint48 disabledTime) = symbioticVaults.atWithTimes(i); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { continue; @@ -550,31 +486,18 @@ contract BoltManager is IBoltManager, Ownable { continue; } - uint256 operatorStake = getSymbioticOperatorStakeAt( - operator, - collateral, - epochStartTs - ); + uint256 operatorStake = getSymbioticOperatorStakeAt(operator, collateral, epochStartTs); if (amount > operatorStake) { revert SlashAmountTooHigh(); } - uint256 vaultStake = IBaseDelegator(IVault(vault).delegator()) - .stakeAt( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), - operator, - epochStartTs, - new bytes(0) - ); + uint256 vaultStake = IBaseDelegator(IVault(vault).delegator()).stakeAt( + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, epochStartTs, new bytes(0) + ); // Slash the vault pro-rata. - _slashSymbioticVault( - epochStartTs, - vault, - operator, - (amount * vaultStake) / operatorStake - ); + _slashSymbioticVault(epochStartTs, vault, operator, (amount * vaultStake) / operatorStake); } } @@ -582,7 +505,9 @@ contract BoltManager is IBoltManager, Ownable { /// @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 { + function registerEigenLayerOperator( + address operator + ) public { if (eigenLayerOperators.contains(operator)) { revert AlreadyRegistered(); } @@ -619,24 +544,18 @@ contract BoltManager is IBoltManager, Ownable { eigenLayerOperators.enable(msg.sender); } - function registerEigenLayerStrategy(address strategy) public { + function registerEigenLayerStrategy( + address strategy + ) public { if (eigenLayerStrategies.contains(strategy)) { revert AlreadyRegistered(); } - if ( - !EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit( - IStrategy(strategy) - ) - ) { + if (!EIGENLAYER_STRATEGY_MANAGER.strategyIsWhitelistedForDeposit(IStrategy(strategy))) { revert StrategyNotAllowed(); } - if ( - !isEigenLayerCollateralWhitelisted( - address(IStrategy(strategy).underlyingToken()) - ) - ) { + if (!isEigenLayerCollateralWhitelisted(address(IStrategy(strategy).underlyingToken()))) { revert CollateralNotWhitelisted(); } @@ -668,8 +587,7 @@ contract BoltManager is IBoltManager, Ownable { function isEigenLayerStrategyEnabled( address strategy ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies - .getTimes(strategy); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.getTimes(strategy); return enabledTime != 0 && disabledTime == 0; } @@ -679,8 +597,7 @@ contract BoltManager is IBoltManager, Ownable { function isEigenLayerOperatorEnabled( address operator ) public view returns (bool) { - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators - .getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); return enabledTime != 0 && disabledTime == 0; } @@ -707,8 +624,7 @@ contract BoltManager is IBoltManager, Ownable { } uint48 epochStartTs = getEpochStartTs(getEpochAtTs(Time.timestamp())); - IBoltValidators.Validator memory validator = validators - .getValidatorByPubkeyHash(pubkeyHash); + IBoltValidators.Validator memory validator = validators.getValidatorByPubkeyHash(pubkeyHash); address operator = validator.authorizedOperator; @@ -716,8 +632,7 @@ contract BoltManager is IBoltManager, Ownable { status.active = validator.exists; status.operator = operator; - (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators - .getTimes(operator); + (uint48 enabledTime, uint48 disabledTime) = eigenLayerOperators.getTimes(operator); if (!_wasEnabledAt(enabledTime, disabledTime, epochStartTs)) { return status; } @@ -726,28 +641,15 @@ contract BoltManager is IBoltManager, Ownable { status.amounts = new uint256[](eigenLayerStrategies.length()); for (uint256 i = 0; i < eigenLayerStrategies.length(); ++i) { - ( - address strategy, - uint48 enabledVaultTime, - uint48 disabledVaultTime - ) = eigenLayerStrategies.atWithTimes(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 - ) - ) { + if (!_wasEnabledAt(enabledVaultTime, disabledVaultTime, epochStartTs)) { continue; } - status.amounts[i] = getEigenLayerOperatorStake( - operator, - collateral - ); + status.amounts[i] = getEigenLayerOperatorStake(operator, collateral); } } @@ -755,10 +657,7 @@ contract BoltManager is IBoltManager, Ownable { // @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) { + function getEigenLayerOperatorStake(address operator, address collateral) public view returns (uint256 amount) { uint48 timestamp = Time.timestamp(); return getEigenLayerOperatorStakeAt(operator, collateral, timestamp); } @@ -783,11 +682,7 @@ contract BoltManager is IBoltManager, Ownable { IStrategy[] memory strategyMem = new IStrategy[](1); for (uint256 i = 0; i < eigenLayerStrategies.length(); i++) { - ( - address strategy, - uint48 enabledTime, - uint48 disabledTime - ) = eigenLayerStrategies.atWithTimes(i); + (address strategy, uint48 enabledTime, uint48 disabledTime) = eigenLayerStrategies.atWithTimes(i); if (collateral != address(IStrategy(strategy).underlyingToken())) { continue; @@ -799,8 +694,7 @@ contract BoltManager is IBoltManager, Ownable { 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); + uint256[] memory shares = EIGENLAYER_DELEGATION_MANAGER.getOperatorShares(operator, strategyMem); amount += IStrategy(strategy).sharesToUnderlyingView(shares[0]); } @@ -811,10 +705,7 @@ contract BoltManager is IBoltManager, Ownable { /// @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) { + 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 @@ -828,11 +719,7 @@ contract BoltManager is IBoltManager, Ownable { // } for (uint256 i; i < eigenLayerOperators.length(); ++i) { - ( - address operator, - uint48 enabledTime, - uint48 disabledTime - ) = eigenLayerOperators.atWithTimes(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)) { @@ -852,20 +739,14 @@ contract BoltManager is IBoltManager, Ownable { address operator, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature ) public { - EIGENLAYER_AVS_DIRECTORY.registerOperatorToAVS( - operator, - operatorSignature - ); + 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; + return EIGENLAYER_AVS_DIRECTORY.avsOperatorStatus(address(this), operator) + == IAVSDirectory.OperatorAVSRegistrationStatus.REGISTERED; } /// @notice Deregister an EigenLayer layer operator from working in Bolt Protocol. @@ -890,45 +771,23 @@ contract BoltManager is IBoltManager, Ownable { /// @param disabledTime The disabled time of the map entry. /// @param timestamp The timestamp to check the map entry status at. /// @return True if the map entry was active at the given timestamp, false otherwise. - function _wasEnabledAt( - uint48 enabledTime, - uint48 disabledTime, - uint48 timestamp - ) private pure returns (bool) { - return - enabledTime != 0 && - enabledTime <= timestamp && - (disabledTime == 0 || disabledTime >= timestamp); + function _wasEnabledAt(uint48 enabledTime, uint48 disabledTime, uint48 timestamp) private pure returns (bool) { + return enabledTime != 0 && enabledTime <= timestamp && (disabledTime == 0 || disabledTime >= timestamp); } /// @notice Slash an operator for a given amount of collateral. /// @param timestamp The timestamp of the slash event. /// @param operator The operator address to slash. /// @param amount The amount of collateral to slash. - function _slashSymbioticVault( - uint48 timestamp, - address vault, - address operator, - uint256 amount - ) private { + function _slashSymbioticVault(uint48 timestamp, address vault, address operator, uint256 amount) private { address slasher = IVault(vault).slasher(); uint256 slasherType = IEntity(slasher).TYPE(); if (slasherType == INSTANT_SLASHER_TYPE) { - ISlasher(slasher).slash( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), - operator, - amount, - timestamp, - new bytes(0) - ); + ISlasher(slasher).slash(BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, amount, timestamp, new bytes(0)); } else if (slasherType == VETO_SLASHER_TYPE) { IVetoSlasher(slasher).requestSlash( - BOLT_SYMBIOTIC_NETWORK.subnetwork(0), - operator, - amount, - timestamp, - new bytes(0) + BOLT_SYMBIOTIC_NETWORK.subnetwork(0), operator, amount, timestamp, new bytes(0) ); } else { revert UnknownSlasherType();