diff --git a/lib/eigenlayer-contracts b/lib/eigenlayer-contracts index d28a5e4a..5e133a14 160000 --- a/lib/eigenlayer-contracts +++ b/lib/eigenlayer-contracts @@ -1 +1 @@ -Subproject commit d28a5e4aaad1984efc8ecb8021b730e23ad60bb1 +Subproject commit 5e133a140bfef2c1ea9990fca79dc6a110ec7a9c diff --git a/src/interfaces/IBN254TableCalculator.sol b/src/interfaces/IBN254TableCalculator.sol index 5383bdaf..938fcc63 100644 --- a/src/interfaces/IBN254TableCalculator.sol +++ b/src/interfaces/IBN254TableCalculator.sol @@ -9,19 +9,21 @@ import { interface IBN254TableCalculator is IOperatorTableCalculator, IOperatorTableCalculatorTypes { /** - * @notice calculates the operatorInfos for a given operatorSet - * @param operatorSet the operatorSet to calculate the operator table for - * @return operatorSetInfo the operatorSetInfo for the given operatorSet + * @notice Calculates the BN254 operator table info for a given operatorSet + * @param operatorSet The operatorSet to calculate the operator table for + * @return operatorSetInfo The BN254OperatorSetInfo containing merkle root, aggregate pubkey, and total weights * @dev The output of this function is used by the multichain protocol to transport operator stake weights to destination chains + * @dev This function aggregates operator weights, creates a merkle tree of operator info, and calculates the aggregate BN254 public key */ function calculateOperatorTable( OperatorSet calldata operatorSet ) external view returns (BN254OperatorSetInfo memory operatorSetInfo); /** - * @notice Get the operatorInfos for a given operatorSet - * @param operatorSet the operatorSet to get the operatorInfos for - * @return operatorInfos the operatorInfos for the given operatorSet + * @notice Get the individual operator infos for a given operatorSet + * @param operatorSet The operatorSet to get the operatorInfos for + * @return operatorInfos The array of BN254OperatorInfo structs containing pubkeys and weights for registered operators + * @dev Only returns operators that have registered their BN254 keys with the KeyRegistrar */ function getOperatorInfos( OperatorSet calldata operatorSet diff --git a/src/interfaces/IECDSATableCalculator.sol b/src/interfaces/IECDSATableCalculator.sol index d7f843cf..2db2c747 100644 --- a/src/interfaces/IECDSATableCalculator.sol +++ b/src/interfaces/IECDSATableCalculator.sol @@ -9,10 +9,11 @@ import { interface IECDSATableCalculator is IOperatorTableCalculator, IOperatorTableCalculatorTypes { /** - * @notice calculates the operatorInfos for a given operatorSet - * @param operatorSet the operatorSet to calculate the operator table for - * @return operatorInfos the list of operatorInfos for the given operatorSet + * @notice Calculates the ECDSA operator infos for a given operatorSet + * @param operatorSet The operatorSet to calculate the operator table for + * @return operatorInfos The array of ECDSAOperatorInfo structs containing ECDSA addresses and weights for registered operators * @dev The output of this function is used by the multichain protocol to transport operator stake weights to destination chains + * @dev Only returns operators that have registered their ECDSA keys with the KeyRegistrar and have non-zero stake */ function calculateOperatorTable( OperatorSet calldata operatorSet diff --git a/src/interfaces/ISocketRegistryV2.sol b/src/interfaces/ISocketRegistryV2.sol index a5014c9f..40743f9e 100644 --- a/src/interfaces/ISocketRegistryV2.sol +++ b/src/interfaces/ISocketRegistryV2.sol @@ -29,6 +29,8 @@ interface ISocketRegistryV2 is ISocketRegistryErrors, ISocketRegistryEvents { * @param operator The operator to set the socket for. * @param socket The socket to set for the operator. * @dev This function can only be called by the operator themselves. + * @dev Reverts for: + * - CallerNotOperator: The caller is not the operator */ function updateSocket(address operator, string memory socket) external; } diff --git a/src/middlewareV2/registrar/AVSRegistrar.sol b/src/middlewareV2/registrar/AVSRegistrar.sol index ff0a7594..def58b14 100644 --- a/src/middlewareV2/registrar/AVSRegistrar.sol +++ b/src/middlewareV2/registrar/AVSRegistrar.sol @@ -39,6 +39,9 @@ abstract contract AVSRegistrar is Initializable, AVSRegistrarStorage { } /// @inheritdoc IAVSRegistrar + /// @dev Reverts for: + /// - NotAllocationManager: The caller is not the allocation manager + /// - KeyNotRegistered: The operator has not registered a key for the given operator sets in the `KeyRegistrar` function registerOperator( address operator, address, /* avs */ @@ -56,6 +59,8 @@ abstract contract AVSRegistrar is Initializable, AVSRegistrarStorage { } /// @inheritdoc IAVSRegistrar + /// @dev Reverts for: + /// - NotAllocationManager: The caller is not the allocation manager function deregisterOperator( address operator, address, /* avs */ @@ -85,6 +90,8 @@ abstract contract AVSRegistrar is Initializable, AVSRegistrarStorage { * @notice Validates that the operator has registered a key for the given operator sets in the `KeyRegistrar` * @param operator The operator to validate * @param operatorSetIds The operator sets to validate + * @dev Reverts for: + * - KeyNotRegistered: The operator has not registered a key for the given operator sets in the `KeyRegistrar` */ function _validateOperatorKeys( address operator, diff --git a/src/middlewareV2/registrar/presets/AVSRegistrarWithAllowlist.sol b/src/middlewareV2/registrar/presets/AVSRegistrarWithAllowlist.sol index 8e85f9dd..9ecc56de 100644 --- a/src/middlewareV2/registrar/presets/AVSRegistrarWithAllowlist.sol +++ b/src/middlewareV2/registrar/presets/AVSRegistrarWithAllowlist.sol @@ -25,6 +25,8 @@ contract AVSRegistrarWithAllowlist is AVSRegistrar, Allowlist, IAVSRegistrarWith } /// @notice Before registering operator, check if the operator is in the allowlist + /// @dev Reverts for: + /// - OperatorNotInAllowlist: The operator is not in the allowlist function _beforeRegisterOperator( address operator, uint32[] calldata operatorSetIds, diff --git a/src/middlewareV2/tableCalculator/BN254TableCalculator.sol b/src/middlewareV2/tableCalculator/BN254TableCalculator.sol index 19e7ce4b..98f70cfa 100644 --- a/src/middlewareV2/tableCalculator/BN254TableCalculator.sol +++ b/src/middlewareV2/tableCalculator/BN254TableCalculator.sol @@ -21,6 +21,13 @@ contract BN254TableCalculator is BN254TableCalculatorBase { /// @notice The default lookahead blocks for the slashable stake lookup uint256 public immutable LOOKAHEAD_BLOCKS; + /** + * @notice Constructor to initialize the BN254TableCalculator + * @param _keyRegistrar The KeyRegistrar contract for managing operator BN254 keys + * @param _allocationManager The AllocationManager contract for operator allocations and slashable stake + * @param _LOOKAHEAD_BLOCKS The number of blocks to look ahead when calculating minimum slashable stake + * @dev The lookahead blocks parameter helps ensure stake calculations account for future slashing events + */ constructor( IKeyRegistrar _keyRegistrar, IAllocationManager _allocationManager, @@ -31,11 +38,14 @@ contract BN254TableCalculator is BN254TableCalculatorBase { } /** - * @notice Get the operator weights for a given operatorSet based on the slashable stake. + * @notice Get the operator weights for a given operatorSet based on the minimum slashable stake. * @param operatorSet The operatorSet to get the weights for - * @return operators The addresses of the operators in the operatorSet + * @return operators The addresses of the operators in the operatorSet with non-zero slashable stake * @return weights The weights for each operator in the operatorSet, this is a 2D array where the first index is the operator * and the second index is the type of weight. In this case its of length 1 and returns the slashable stake for the operatorSet. + * @dev This implementation sums the minimum slashable stake across all strategies for each operator + * @dev Only includes operators with non-zero total slashable stake to optimize gas usage + * @dev The weights array contains only one element per operator representing their total slashable stake */ function _getOperatorWeights( OperatorSet calldata operatorSet diff --git a/src/middlewareV2/tableCalculator/BN254TableCalculatorBase.sol b/src/middlewareV2/tableCalculator/BN254TableCalculatorBase.sol index 13c2d0d6..0d42e58e 100644 --- a/src/middlewareV2/tableCalculator/BN254TableCalculatorBase.sol +++ b/src/middlewareV2/tableCalculator/BN254TableCalculatorBase.sol @@ -7,6 +7,8 @@ import {IOperatorTableCalculator} from import {IKeyRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IKeyRegistrar.sol"; import {Merkle} from "eigenlayer-contracts/src/contracts/libraries/Merkle.sol"; import {BN254} from "eigenlayer-contracts/src/contracts/libraries/BN254.sol"; +import {LeafCalculatorMixin} from + "eigenlayer-contracts/src/contracts/mixins/LeafCalculatorMixin.sol"; import {IBN254TableCalculator} from "../../interfaces/IBN254TableCalculator.sol"; /** @@ -15,7 +17,7 @@ import {IBN254TableCalculator} from "../../interfaces/IBN254TableCalculator.sol" * @dev This contract contains all the core logic for operator table calculations, * with weight calculation left to be implemented by derived contracts */ -abstract contract BN254TableCalculatorBase is IBN254TableCalculator { +abstract contract BN254TableCalculatorBase is IBN254TableCalculator, LeafCalculatorMixin { using Merkle for bytes32[]; using BN254 for BN254.G1Point; @@ -23,6 +25,10 @@ abstract contract BN254TableCalculatorBase is IBN254TableCalculator { /// @notice KeyRegistrar contract for managing operator keys IKeyRegistrar public immutable keyRegistrar; + /** + * @notice Constructor to initialize the BN254TableCalculatorBase + * @param _keyRegistrar The KeyRegistrar contract for managing operator BN254 public keys + */ constructor( IKeyRegistrar _keyRegistrar ) { @@ -68,6 +74,9 @@ abstract contract BN254TableCalculatorBase is IBN254TableCalculator { } /// @inheritdoc IBN254TableCalculator + /** + * @dev Only returns operators that have registered their BN254 keys with the KeyRegistrar + */ function getOperatorInfos( OperatorSet calldata operatorSet ) external view virtual returns (BN254OperatorInfo[] memory) { @@ -109,13 +118,14 @@ abstract contract BN254TableCalculatorBase is IBN254TableCalculator { /** * @notice Calculates the operator table for a given operatorSet, also calculates the aggregate pubkey for the operatorSet * @param operatorSet The operatorSet to calculate the operator table for - * @return operatorSetInfo The operator table for the given operatorSet + * @return operatorSetInfo The BN254OperatorSetInfo containing merkle root, operator count, aggregate pubkey, and total weights * @dev This function: * 1. Gets operator weights from the weight calculator * 2. Collates weights into total weights * 3. Creates a merkle tree of operator info * - assumes that the operator has a registered BN254 key * 4. Calculates the aggregate public key + * @dev Returns empty operator set info if no operators have registered keys or non-zero weights */ function _calculateOperatorTable( OperatorSet calldata operatorSet @@ -152,8 +162,10 @@ abstract contract BN254TableCalculatorBase is IBN254TableCalculator { totalWeights[j] += weights[i][j]; } (BN254.G1Point memory g1Point,) = keyRegistrar.getBN254Key(operatorSet, operators[i]); + + // Use `LeafCalculatorMixin` to calculate the leaf hash for the operator info operatorInfoLeaves[operatorCount] = - keccak256(abi.encode(BN254OperatorInfo({pubkey: g1Point, weights: weights[i]}))); + calculateOperatorInfoLeaf(BN254OperatorInfo({pubkey: g1Point, weights: weights[i]})); // Add the operator's G1 point to the aggregate pubkey aggregatePubkey = aggregatePubkey.plus(g1Point); diff --git a/src/middlewareV2/tableCalculator/ECDSATableCalculator.sol b/src/middlewareV2/tableCalculator/ECDSATableCalculator.sol index 44f2c1c6..e7e658ce 100644 --- a/src/middlewareV2/tableCalculator/ECDSATableCalculator.sol +++ b/src/middlewareV2/tableCalculator/ECDSATableCalculator.sol @@ -21,6 +21,13 @@ contract ECDSATableCalculator is ECDSATableCalculatorBase { /// @notice The default lookahead blocks for the slashable stake lookup uint256 public immutable LOOKAHEAD_BLOCKS; + /** + * @notice Constructor to initialize the ECDSATableCalculator + * @param _keyRegistrar The KeyRegistrar contract for managing operator ECDSA keys + * @param _allocationManager The AllocationManager contract for operator allocations and slashable stake + * @param _LOOKAHEAD_BLOCKS The number of blocks to look ahead when calculating minimum slashable stake + * @dev The lookahead blocks parameter helps ensure stake calculations account for future slashing events + */ constructor( IKeyRegistrar _keyRegistrar, IAllocationManager _allocationManager, @@ -31,11 +38,14 @@ contract ECDSATableCalculator is ECDSATableCalculatorBase { } /** - * @notice Get the operator weights for a given operatorSet based on the slashable stake. + * @notice Get the operator weights for a given operatorSet based on the minimum slashable stake. * @param operatorSet The operatorSet to get the weights for - * @return operators The addresses of the operators in the operatorSet + * @return operators The addresses of the operators in the operatorSet with non-zero slashable stake * @return weights The weights for each operator in the operatorSet, this is a 2D array where the first index is the operator * and the second index is the type of weight. In this case it's of length 1 and returns the slashable stake for the operatorSet. + * @dev This implementation sums the minimum slashable stake across all strategies for each operator + * @dev Only includes operators with non-zero total slashable stake to optimize gas usage + * @dev The weights array contains only one element per operator representing their total slashable stake */ function _getOperatorWeights( OperatorSet calldata operatorSet diff --git a/src/middlewareV2/tableCalculator/ECDSATableCalculatorBase.sol b/src/middlewareV2/tableCalculator/ECDSATableCalculatorBase.sol index 9361aad6..a6dcf9c2 100644 --- a/src/middlewareV2/tableCalculator/ECDSATableCalculatorBase.sol +++ b/src/middlewareV2/tableCalculator/ECDSATableCalculatorBase.sol @@ -18,6 +18,10 @@ abstract contract ECDSATableCalculatorBase is IECDSATableCalculator { /// @notice KeyRegistrar contract for managing operator keys IKeyRegistrar public immutable keyRegistrar; + /** + * @notice Constructor to initialize the ECDSATableCalculatorBase + * @param _keyRegistrar The KeyRegistrar contract for managing operator ECDSA public keys + */ constructor( IKeyRegistrar _keyRegistrar ) { @@ -25,6 +29,9 @@ abstract contract ECDSATableCalculatorBase is IECDSATableCalculator { } /// @inheritdoc IECDSATableCalculator + /** + * @dev Only returns operators that have registered their ECDSA keys with the KeyRegistrar and have non-zero stake + */ function calculateOperatorTable( OperatorSet calldata operatorSet ) external view virtual returns (ECDSAOperatorInfo[] memory operatorInfos) { @@ -81,10 +88,11 @@ abstract contract ECDSATableCalculatorBase is IECDSATableCalculator { /** * @notice Calculates the operator table for a given operatorSet * @param operatorSet The operatorSet to calculate the operator table for - * @return operatorInfos The operator table for the given operatorSet + * @return operatorInfos The array of ECDSAOperatorInfo structs for operators with registered ECDSA keys * @dev This function: * 1. Gets operator weights from the weight calculator * 2. Creates ECDSAOperatorInfo structs for each operator with registered ECDSA keys + * @dev Returns empty array if no operators have registered keys or non-zero weights */ function _calculateOperatorTable( OperatorSet calldata operatorSet diff --git a/test/unit/middlewareV2/BN254TableCalculatorBaseUnit.t.sol b/test/unit/middlewareV2/BN254TableCalculatorBaseUnit.t.sol index 65c5ee1d..29b83612 100644 --- a/test/unit/middlewareV2/BN254TableCalculatorBaseUnit.t.sol +++ b/test/unit/middlewareV2/BN254TableCalculatorBaseUnit.t.sol @@ -22,6 +22,8 @@ import {BN254TableCalculatorBase} from import {MockEigenLayerDeployer} from "./MockDeployer.sol"; import {Random} from "test/utils/Random.sol"; import {Merkle} from "eigenlayer-contracts/src/contracts/libraries/Merkle.sol"; +import {LeafCalculatorMixin} from + "eigenlayer-contracts/src/contracts/mixins/LeafCalculatorMixin.sol"; // Mock implementation for testing abstract contract contract BN254TableCalculatorBaseHarness is BN254TableCalculatorBase { @@ -61,7 +63,8 @@ contract BN254TableCalculatorBaseHarness is BN254TableCalculatorBase { contract BN254TableCalculatorBaseUnitTests is MockEigenLayerDeployer, IOperatorTableCalculatorTypes, - IKeyRegistrarTypes + IKeyRegistrarTypes, + LeafCalculatorMixin { using BN254 for BN254.G1Point; using OperatorSetLib for OperatorSet; @@ -216,10 +219,8 @@ contract BN254TableCalculatorBaseUnitTests is BN254.G1Point memory pubkey, uint256[] memory weights ) internal pure returns (bytes32) { - return keccak256( - abi.encode( - IOperatorTableCalculatorTypes.BN254OperatorInfo({pubkey: pubkey, weights: weights}) - ) + return calculateOperatorInfoLeaf( + IOperatorTableCalculatorTypes.BN254OperatorInfo({pubkey: pubkey, weights: weights}) ); } }