Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/periphery/ejection/EigenDAEjectionManager.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {IEigenDAEjectionManager} from "src/periphery/ejection/IEigenDAEjectionManager.sol";
import {EigenDAEjectionLib, EigenDAEjectionTypes} from "src/periphery/ejection/libraries/EigenDAEjectionLib.sol";
import {SafeERC20, IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {IRegistryCoordinator} from "lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol";
import {IEigenDADirectory} from "src/core/interfaces/IEigenDADirectory.sol";
import {IIndexRegistry} from "lib/eigenlayer-middleware/src/interfaces/IIndexRegistry.sol";
import {IStakeRegistry} from "lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol";
import {IBLSApkRegistry} from "lib/eigenlayer-middleware/src/interfaces/IBLSApkRegistry.sol";
import {BLSSignatureChecker} from "lib/eigenlayer-middleware/src/BLSSignatureChecker.sol";
import {BN254} from "lib/eigenlayer-middleware/src/libraries/BN254.sol";
import {AddressDirectoryLib} from "src/core/libraries/v3/address-directory/AddressDirectoryLib.sol";
import {AddressDirectoryConstants} from "src/core/libraries/v3/address-directory/AddressDirectoryConstants.sol";
import {AccessControlConstants} from "src/core/libraries/v3/access-control/AccessControlConstants.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {IEigenDASemVer} from "src/core/interfaces/IEigenDASemVer.sol";
contract EigenDAEjectionManager is IEigenDAEjectionManager, IEigenDASemVer {
using AddressDirectoryLib for string;
using EigenDAEjectionLib for address;
using SafeERC20 for IERC20;
address internal immutable _depositToken;
address internal immutable _addressDirectory;
uint256 internal immutable _estimatedGasUsedWithoutSig;
uint256 internal immutable _estimatedGasUsedWithSig;
uint256 internal immutable _depositBaseFeeMultiplier;
bytes32 internal constant CANCEL_EJECTION_MESSAGE_IDENTIFIER = keccak256(
"CancelEjection(address operator,uint64 proceedingTime,uint64 lastProceedingInitiated,bytes quorums,address recipient)"
);
constructor(
address depositToken_,
uint256 depositBaseFeeMultiplier_,
address addressDirectory_,
uint256 estimatedGasUsedWithoutSig_,
uint256 estimatedGasUsedWithSig_
) {
_depositToken = depositToken_;
_depositBaseFeeMultiplier = depositBaseFeeMultiplier_;
_addressDirectory = addressDirectory_;
_estimatedGasUsedWithoutSig = estimatedGasUsedWithoutSig_;
_estimatedGasUsedWithSig = estimatedGasUsedWithSig_;
}
modifier onlyOwner(address sender) {
_onlyOwner(sender);
_;
}
modifier onlyEjector(address sender) {
_onlyEjector(sender);
_;
}
/// OWNER FUNCTIONS
/// @inheritdoc IEigenDAEjectionManager
function setDelay(uint64 delay) external onlyOwner(msg.sender) {
EigenDAEjectionLib.setDelay(delay);
}
/// @inheritdoc IEigenDAEjectionManager
function setCooldown(uint64 cooldown) external onlyOwner(msg.sender) {
EigenDAEjectionLib.setCooldown(cooldown);
}
/// EJECTOR FUNCTIONS
/// @inheritdoc IEigenDAEjectionManager
function addEjectorBalance(uint256 amount) external onlyEjector(msg.sender) {
msg.sender.addEjectorBalance(amount);
IERC20(_depositToken).safeTransferFrom(msg.sender, address(this), amount);
}
/// @inheritdoc IEigenDAEjectionManager
function withdrawEjectorBalance(uint256 amount) external onlyEjector(msg.sender) {
msg.sender.subtractEjectorBalance(amount);
IERC20(_depositToken).safeTransfer(msg.sender, amount);
}
/// @inheritdoc IEigenDAEjectionManager
function startEjection(address operator, bytes memory quorums) external onlyEjector(msg.sender) {
uint256 depositAmount = _depositAmount();
msg.sender.subtractEjectorBalance(depositAmount);
operator.startEjection(msg.sender, quorums, depositAmount);
}
/// @inheritdoc IEigenDAEjectionManager
function cancelEjectionByEjector(address operator) external onlyEjector(msg.sender) {
uint256 depositAmount = operator.getDepositAmount();
operator.cancelEjection();
operator.getEjector().addEjectorBalance(depositAmount);
}
/// @inheritdoc IEigenDAEjectionManager
function completeEjection(address operator, bytes memory quorums) external onlyEjector(msg.sender) {
uint256 depositAmount = operator.getDepositAmount();
operator.completeEjection(quorums);
_tryEjectOperator(operator, quorums);
operator.getEjector().addEjectorBalance(depositAmount);
}
/// OPERATOR FUNCTIONS
/// @inheritdoc IEigenDAEjectionManager
function cancelEjectionWithSig(
address operator,
BN254.G2Point memory apkG2,
BN254.G1Point memory sigma,
address recipient
) external {
address blsApkRegistry =
IEigenDADirectory(_addressDirectory).getAddress(AddressDirectoryConstants.BLS_APK_REGISTRY_NAME.getKey());
(BN254.G1Point memory apk,) = IBLSApkRegistry(blsApkRegistry).getRegisteredPubkey(operator);
_verifySig(_cancelEjectionMessageHash(operator, recipient), apk, apkG2, sigma);
operator.cancelEjection();
_refundGas(recipient, _estimatedGasUsedWithSig);
}
/// @inheritdoc IEigenDAEjectionManager
function cancelEjection() external {
msg.sender.cancelEjection();
_refundGas(msg.sender, _estimatedGasUsedWithoutSig);
}
/// GETTERS
/// @inheritdoc IEigenDAEjectionManager
function getDepositToken() external view returns (address) {
return _depositToken;
}
/// @inheritdoc IEigenDAEjectionManager
function getEjector(address operator) external view returns (address) {
return operator.getEjector();
}
/// @inheritdoc IEigenDAEjectionManager
function ejectionTime(address operator) external view returns (uint64) {
return EigenDAEjectionLib.ejectionParams(operator).proceedingTime;
}
/// @inheritdoc IEigenDAEjectionManager
function lastEjectionInitiated(address operator) external view returns (uint64) {
return operator.lastProceedingInitiated();
}
/// @inheritdoc IEigenDAEjectionManager
function ejectionQuorums(address operator) external view returns (bytes memory) {
return EigenDAEjectionLib.ejectionParams(operator).quorums;
}
/// @inheritdoc IEigenDAEjectionManager
function ejectionDelay() external view returns (uint64) {
return EigenDAEjectionLib.getDelay();
}
/// @inheritdoc IEigenDAEjectionManager
function ejectionCooldown() external view returns (uint64) {
return EigenDAEjectionLib.getCooldown();
}
/// @inheritdoc IEigenDASemVer
function semver() external pure returns (uint8 major, uint8 minor, uint8 patch) {
return (3, 0, 0);
}
/// INTERNAL FUNCTIONS
function _isOperatorWeightsGreater(address operator1, address operator2, bytes memory quorumNumbers)
internal
view
returns (bool)
{
uint96[] memory weights1 = _getOperatorWeights(operator1, quorumNumbers);
uint96[] memory weights2 = _getOperatorWeights(operator2, quorumNumbers);
for (uint256 i; i < weights1.length; i++) {
if (weights1[i] <= weights2[i]) {
return false;
}
}
return true;
}
function _getOperatorWeights(address operator, bytes memory quorumNumbers)
internal
view
returns (uint96[] memory weights)
{
address stakeRegistry =
IEigenDADirectory(_addressDirectory).getAddress(AddressDirectoryConstants.STAKE_REGISTRY_NAME.getKey());
weights = new uint96[](quorumNumbers.length);
for (uint256 i; i < quorumNumbers.length; i++) {
uint8 quorumNumber = uint8(quorumNumbers[i]);
weights[i] = IStakeRegistry(stakeRegistry).weightOfOperatorForQuorum(quorumNumber, operator);
}
}
/// @notice Returns the required deposit for initiating an ejection based on a multiple of the base fee of the block.
function _depositAmount() internal virtual returns (uint256) {
return _estimatedGasUsedWithSig * block.basefee * _depositBaseFeeMultiplier;
}
function _refundGas(address receiver, uint256 estimatedGasUsed) internal virtual {
uint256 estimatedRefund = estimatedGasUsed * block.basefee;
uint256 depositAmount = EigenDAEjectionLib.ejectionParams(receiver).depositAmount;
IERC20(_depositToken).safeTransfer(receiver, estimatedRefund > depositAmount ? depositAmount : estimatedRefund);
}
/// @notice Attempts to eject an operator. If the ejection fails, it catches the error and does nothing.
function _tryEjectOperator(address operator, bytes memory quorums) internal {
address registryCoordinator = IEigenDADirectory(_addressDirectory).getAddress(
AddressDirectoryConstants.REGISTRY_COORDINATOR_NAME.getKey()
);
try IRegistryCoordinator(registryCoordinator).ejectOperator(operator, quorums) {} catch {}
}
/// @notice Defines a unique identifier for a cancel ejection message to be signed by an operator for the purpose of authorizing a cancellation.
function _cancelEjectionMessageHash(address operator, address recipient) internal view returns (bytes32) {
return keccak256(
abi.encode(
CANCEL_EJECTION_MESSAGE_IDENTIFIER,
block.chainid,
address(this),
EigenDAEjectionLib.ejectionParams(operator),
recipient
)
);
}
function _verifySig(
bytes32 messageHash,
BN254.G1Point memory apk,
BN254.G2Point memory apkG2,
BN254.G1Point memory sigma
) internal view {
address signatureVerifier =
IEigenDADirectory(_addressDirectory).getAddress(AddressDirectoryConstants.SERVICE_MANAGER_NAME.getKey());
(bool paired, bool valid) =
BLSSignatureChecker(signatureVerifier).trySignatureAndApkVerification(messageHash, apk, apkG2, sigma);
require(paired, "EigenDAEjectionManager: Pairing failed");
require(valid, "EigenDAEjectionManager: Invalid signature");
}
function _onlyOwner(address sender) internal view virtual {
require(
IAccessControl(
IEigenDADirectory(_addressDirectory).getAddress(AddressDirectoryConstants.ACCESS_CONTROL_NAME.getKey())
).hasRole(AccessControlConstants.OWNER_ROLE, sender),
"EigenDAEjectionManager: Caller is not the owner"
);
}
function _onlyEjector(address sender) internal view virtual {
require(
IAccessControl(
IEigenDADirectory(_addressDirectory).getAddress(AddressDirectoryConstants.ACCESS_CONTROL_NAME.getKey())
).hasRole(AccessControlConstants.EJECTOR_ROLE, sender),
"EigenDAEjectionManager: Caller is not an ejector"
);
}
}
"
},
"src/periphery/ejection/IEigenDAEjectionManager.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {BN254} from "lib/eigenlayer-middleware/src/libraries/BN254.sol";
interface IEigenDAEjectionManager {
/// @notice Adds to an escrow for the ejector to use in ejection processes.
function addEjectorBalance(uint256 amount) external;
/// @notice Withdraws from the ejector's escrow balance that is not currently in use for an ejection process.
function withdrawEjectorBalance(uint256 amount) external;
/// @notice Sets the delay for ejection processes.
/// @param delay The number of seconds that must pass after initiation before an ejection can be completed.
/// This is also the time guaranteed to a challenger to cancel the ejection.
function setDelay(uint64 delay) external;
/// @notice Sets the cooldown for ejection processes.
/// @param cooldown The number of seconds that must pass before a new ejection can be initiated after a previous one.
function setCooldown(uint64 cooldown) external;
/// @notice Starts the ejection process for an operator. Takes a deposit from the ejector.
/// @param operator The address of the operator to eject.
/// @param quorums The quorums associated with the ejection process.
function startEjection(address operator, bytes memory quorums) external;
/// @notice Cancels the ejection process initiated by a ejector.
/// @dev Any ejector can cancel an ejection process, but the deposit is returned to the ejector who initiated it.
function cancelEjectionByEjector(address operator) external;
/// @notice Completes the ejection process for an operator. Transfers the deposit back to the ejector.
/// @dev Any ejector can complete an ejection process, but the deposit is returned to the ejector who initiated it.
function completeEjection(address operator, bytes memory quorums) external;
/// @notice Cancels the ejection process for a given operator with their signature. Refunds the deposit to the recipient.
/// @param operator The address of the operator whose ejection is being cancelled.
/// @param apkG2 The G2 point of the operator's public key.
/// @param sigma The BLS signature of the operator.
/// @param recipient The address to which the gas refund will be sent.
function cancelEjectionWithSig(
address operator,
BN254.G2Point memory apkG2,
BN254.G1Point memory sigma,
address recipient
) external;
/// @notice Cancels the ejection process for the message sender. Refunds gas to the caller.
function cancelEjection() external;
/// @notice Returns the address of the token used for ejection deposits and refunds.
function getDepositToken() external view returns (address);
/// @notice Returns the address of the ejector for a given operator. If the returned address is zero, then there is no ejection in progress.
function getEjector(address operator) external view returns (address);
/// @notice Returns whether an ejection process has been initiated for a given operator.
function ejectionTime(address operator) external view returns (uint64);
/// @notice Returns the timestamp of the last ejection proceeding initiated for a given operator.
function lastEjectionInitiated(address operator) external view returns (uint64);
/// @notice Returns the quorums associated with the ejection process for a given operator.
function ejectionQuorums(address operator) external view returns (bytes memory);
/// @notice Returns the delay for ejection processes.
function ejectionDelay() external view returns (uint64);
/// @notice Returns the cooldown for ejection initiations per operator.
function ejectionCooldown() external view returns (uint64);
}
"
},
"src/periphery/ejection/libraries/EigenDAEjectionLib.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {EigenDAEjectionTypes} from "src/periphery/ejection/libraries/EigenDAEjectionTypes.sol";
import {EigenDAEjectionStorage} from "src/periphery/ejection/libraries/EigenDAEjectionStorage.sol";
library EigenDAEjectionLib {
event EjectionStarted(
address operator,
address ejector,
bytes quorums,
uint64 timestampStarted,
uint64 ejectionTime,
uint256 depositAmount
);
event EjectionCancelled(address operator);
event EjectionCompleted(address operator, bytes quorums);
event DelaySet(uint64 delay);
event CooldownSet(uint64 cooldown);
/// @notice Sets the delay for ejection processes.
function setDelay(uint64 delay) internal {
s().delay = delay;
emit DelaySet(delay);
}
/// @notice Sets the cooldown for ejection processes.
function setCooldown(uint64 cooldown) internal {
s().cooldown = cooldown;
emit CooldownSet(cooldown);
}
/// @notice Starts an ejection process for an operator.
function startEjection(address operator, address ejector, bytes memory quorums, uint256 depositAmount) internal {
EigenDAEjectionTypes.Ejectee storage ejectee = s().ejectionParams[operator];
require(ejectee.params.proceedingTime == 0, "Ejection already in progress");
require(ejectee.lastProceedingInitiated + s().cooldown <= block.timestamp, "Ejection cooldown not met");
ejectee.params.ejector = ejector;
ejectee.params.quorums = quorums;
ejectee.params.proceedingTime = uint64(block.timestamp) + s().delay;
ejectee.params.depositAmount = depositAmount;
ejectee.lastProceedingInitiated = uint64(block.timestamp);
emit EjectionStarted(
operator, ejector, quorums, ejectee.lastProceedingInitiated, ejectee.params.proceedingTime, depositAmount
);
}
/// @notice Cancels an ejection process for an operator.
function cancelEjection(address operator) internal {
EigenDAEjectionTypes.Ejectee storage ejectee = s().ejectionParams[operator];
require(ejectee.params.proceedingTime > 0, "No ejection in progress");
deleteEjection(operator);
emit EjectionCancelled(operator);
}
/// @notice Completes an ejection process for an operator.
function completeEjection(address operator, bytes memory quorums) internal {
require(quorumsEqual(s().ejectionParams[operator].params.quorums, quorums), "Quorums do not match");
EigenDAEjectionTypes.Ejectee storage ejectee = s().ejectionParams[operator];
require(ejectee.params.proceedingTime > 0, "No proceeding in progress");
require(block.timestamp >= ejectee.params.proceedingTime, "Proceeding not yet due");
deleteEjection(operator);
emit EjectionCompleted(operator, quorums);
}
/// @notice Helper function to clear an ejection.
/// @dev The lastProceedingInitiated field is not cleared to allow cooldown enforcement.
function deleteEjection(address operator) internal {
EigenDAEjectionTypes.Ejectee storage ejectee = s().ejectionParams[operator];
ejectee.params.ejector = address(0);
ejectee.params.quorums = hex"";
ejectee.params.proceedingTime = 0;
ejectee.params.depositAmount = 0;
}
/// @notice Adds to the ejector's balance for ejection processes.
/// @dev This function does not handle tokens
function addEjectorBalance(address ejector, uint256 amount) internal {
s().ejectorBalance[ejector] += amount;
}
/// @notice Subtracts from the ejector's balance for ejection processes.
/// @dev This function does not handle tokens
function subtractEjectorBalance(address ejector, uint256 amount) internal {
require(s().ejectorBalance[ejector] >= amount, "Insufficient balance");
// no underflow check needed
unchecked {
s().ejectorBalance[ejector] -= amount;
}
}
/// @notice Returns the address of the ejector for a given operator.
/// @dev If the address is zero, it means no ejection is in progress.
function getEjector(address operator) internal view returns (address ejector) {
return s().ejectionParams[operator].params.ejector;
}
function getDepositAmount(address operator) internal view returns (uint256 depositAmount) {
return s().ejectionParams[operator].params.depositAmount;
}
function lastProceedingInitiated(address operator) internal view returns (uint64) {
return s().ejectionParams[operator].lastProceedingInitiated;
}
/// @notice Compares two quorums to see if they are equal.
function quorumsEqual(bytes memory quorums1, bytes memory quorums2) internal pure returns (bool) {
return keccak256(quorums1) == keccak256(quorums2);
}
function ejectionParams(address operator) internal view returns (EigenDAEjectionTypes.EjectionParams storage) {
return s().ejectionParams[operator].params;
}
/// @return The amount of time that must elapse from initialization before an ejection can be completed.
function getDelay() internal view returns (uint64) {
return s().delay;
}
/// @return The amount of time that must elapse after an ejection is initiated before another can be initiated for an operator.
function getCooldown() internal view returns (uint64) {
return s().cooldown;
}
/// @notice Returns the ejection storage.
function s() private pure returns (EigenDAEjectionStorage.Layout storage) {
return EigenDAEjectionStorage.layout();
}
}
"
},
"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
"
},
"lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;
import {IBLSApkRegistry} from "./IBLSApkRegistry.sol";
import {IStakeRegistry} from "./IStakeRegistry.sol";
import {IIndexRegistry} from "./IIndexRegistry.sol";
import {ISocketRegistry} from "./ISocketRegistry.sol";
import {BN254} from "../libraries/BN254.sol";
/**
* @title Interface for a contract that coordinates between various registries for an AVS.
* @author Layr Labs, Inc.
*/
interface IRegistryCoordinator {
// EVENTS
/// Emits when an operator is registered
event OperatorRegistered(address indexed operator, bytes32 indexed operatorId);
/// Emits when an operator is deregistered
event OperatorDeregistered(address indexed operator, bytes32 indexed operatorId);
event OperatorSetParamsUpdated(uint8 indexed quorumNumber, OperatorSetParam operatorSetParams);
event ChurnApproverUpdated(address prevChurnApprover, address newChurnApprover);
event EjectorUpdated(address prevEjector, address newEjector);
event OperatorSocketUpdate(bytes32 indexed operatorId, string socket);
/// @notice emitted when all the operators for a quorum are updated at once
event QuorumBlockNumberUpdated(uint8 indexed quorumNumber, uint256 blocknumber);
// DATA STRUCTURES
enum OperatorStatus {
// default is NEVER_REGISTERED
NEVER_REGISTERED,
REGISTERED,
DEREGISTERED
}
// STRUCTS
/**
* @notice Data structure for storing info on operators
*/
struct OperatorInfo {
// the id of the operator, which is likely the keccak256 hash of the operator's public key if using BLSRegistry
bytes32 operatorId;
// indicates whether the operator is actively registered for serving the middleware or not
OperatorStatus status;
}
/**
* @notice Data structure for storing info on quorum bitmap updates where the `quorumBitmap` is the bitmap of the
* quorums the operator is registered for starting at (inclusive)`updateBlockNumber` and ending at (exclusive) `nextUpdateBlockNumber`
* @dev nextUpdateBlockNumber is initialized to 0 for the latest update
*/
struct QuorumBitmapUpdate {
uint32 updateBlockNumber;
uint32 nextUpdateBlockNumber;
uint192 quorumBitmap;
}
/**
* @notice Data structure for storing operator set params for a given quorum. Specifically the
* `maxOperatorCount` is the maximum number of operators that can be registered for the quorum,
* `kickBIPsOfOperatorStake` is the basis points of a new operator needs to have of an operator they are trying to kick from the quorum,
* and `kickBIPsOfTotalStake` is the basis points of the total stake of the quorum that an operator needs to be below to be kicked.
*/
struct OperatorSetParam {
uint32 maxOperatorCount;
uint16 kickBIPsOfOperatorStake;
uint16 kickBIPsOfTotalStake;
}
/**
* @notice Data structure for the parameters needed to kick an operator from a quorum with number `quorumNumber`, used during registration churn.
* `operator` is the address of the operator to kick
*/
struct OperatorKickParam {
uint8 quorumNumber;
address operator;
}
/// @notice Returns the operator set params for the given `quorumNumber`
function getOperatorSetParams(uint8 quorumNumber) external view returns (OperatorSetParam memory);
/// @notice the Stake registry contract that will keep track of operators' stakes
function stakeRegistry() external view returns (IStakeRegistry);
/// @notice the BLS Aggregate Pubkey Registry contract that will keep track of operators' BLS aggregate pubkeys per quorum
function blsApkRegistry() external view returns (IBLSApkRegistry);
/// @notice the index Registry contract that will keep track of operators' indexes
function indexRegistry() external view returns (IIndexRegistry);
/// @notice the Socket Registry contract that will keep track of operators' sockets
function socketRegistry() external view returns (ISocketRegistry);
/**
* @notice Ejects the provided operator from the provided quorums from the AVS
* @param operator is the operator to eject
* @param quorumNumbers are the quorum numbers to eject the operator from
*/
function ejectOperator(address operator, bytes calldata quorumNumbers) external;
/// @notice Returns the number of quorums the registry coordinator has created
function quorumCount() external view returns (uint8);
/// @notice Returns the operator struct for the given `operator`
function getOperator(address operator) external view returns (OperatorInfo memory);
/// @notice Returns the operatorId for the given `operator`
function getOperatorId(address operator) external view returns (bytes32);
/// @notice Returns the operator address for the given `operatorId`
function getOperatorFromId(bytes32 operatorId) external view returns (address operator);
/// @notice Returns the status for the given `operator`
function getOperatorStatus(address operator) external view returns (IRegistryCoordinator.OperatorStatus);
/// @notice Returns the indices of the quorumBitmaps for the provided `operatorIds` at the given `blockNumber`
function getQuorumBitmapIndicesAtBlockNumber(uint32 blockNumber, bytes32[] memory operatorIds)
external
view
returns (uint32[] memory);
/**
* @notice Returns the quorum bitmap for the given `operatorId` at the given `blockNumber` via the `index`
* @dev reverts if `index` is incorrect
*/
function getQuorumBitmapAtBlockNumberByIndex(bytes32 operatorId, uint32 blockNumber, uint256 index)
external
view
returns (uint192);
/// @notice Returns the `index`th entry in the operator with `operatorId`'s bitmap history
function getQuorumBitmapUpdateByIndex(bytes32 operatorId, uint256 index)
external
view
returns (QuorumBitmapUpdate memory);
/// @notice Returns the current quorum bitmap for the given `operatorId`
function getCurrentQuorumBitmap(bytes32 operatorId) external view returns (uint192);
/// @notice Returns the length of the quorum bitmap history for the given `operatorId`
function getQuorumBitmapHistoryLength(bytes32 operatorId) external view returns (uint256);
/// @notice Returns the registry at the desired index
function registries(uint256) external view returns (address);
/// @notice Returns the number of registries
function numRegistries() external view returns (uint256);
/**
* @notice Returns the message hash that an operator must sign to register their BLS public key.
* @param operator is the address of the operator registering their BLS public key
*/
function pubkeyRegistrationMessageHash(address operator) external view returns (BN254.G1Point memory);
/// @notice returns the blocknumber the quorum was last updated all at once for all operators
function quorumUpdateBlockNumber(uint8 quorumNumber) external view returns (uint256);
/// @notice The owner of the registry coordinator
function owner() external view returns (address);
/**
* @notice Updates the socket of the msg.sender given they are a registered operator
* @param socket is the new socket of the operator
*/
function updateSocket(string memory socket) external;
}
"
},
"src/core/interfaces/IEigenDADirectory.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import {ConfigRegistryTypes} from "src/core/libraries/v3/config-registry/ConfigRegistryTypes.sol";
interface IEigenDAAddressDirectory {
error AddressAlreadyExists(string name);
error AddressDoesNotExist(string name);
error ZeroAddress();
error NewValueIsOldValue(address value);
event AddressAdded(string name, bytes32 indexed key, address indexed value);
event AddressReplaced(string name, bytes32 indexed key, address indexed oldValue, address indexed newValue);
event AddressRemoved(string name, bytes32 indexed key);
/// @notice Adds a new address to the directory by name.
/// @dev Fails if the address is zero or if an address with the same name already exists.
/// Emits an AddressAdded event on success.
function addAddress(string memory name, address value) external;
/// @notice Replaces an existing address in the directory by name.
/// @dev Fails if the address is zero, if the address with the name does not exist, or if the new value is the same as the old value.
/// Emits an AddressReplaced event on success.
function replaceAddress(string memory name, address value) external;
/// @notice Removes an address from the directory by name.
/// @dev Fails if the address with the name does not exist.
/// Emits an AddressRemoved event on success.
function removeAddress(string memory name) external;
/// @notice Gets the address by keccak256 hash of the name.
/// @dev This entry point is cheaper in gas because it avoids needing to compute the key from the name.
function getAddress(bytes32 key) external view returns (address);
/// @notice Gets the address by name.
function getAddress(string memory name) external view returns (address);
/// @notice Gets the name by keccak256 hash of the name.
function getName(bytes32 key) external view returns (string memory);
/// @notice Gets all names in the directory.
function getAllNames() external view returns (string[] memory);
}
/// @title IEigenDAConfigRegistry
/// @notice Interface for a configuration registry that allows adding and retrieving configuration entries by name.
/// Supports both bytes32 and bytes types for configuration values, and maintains a checkpointed structure for each configuration entry
/// by an arbitrary activation key.
interface IEigenDAConfigRegistry {
/// @notice Adds a 32 byte configuration value to the configuration registry.
/// @param name The name of the configuration entry.
/// @param activationKey The activation key for the configuration entry.
/// This is an arbitrary key defined by the caller to indicate when the configuration should become active.
/// @param value The 32 byte configuration value.
function addConfigBytes32(string memory name, uint256 activationKey, bytes32 value) external;
/// @notice Adds a variable length byte configuration value to the configuration registry.
/// @param name The name of the configuration entry.
/// @param activationKey The activation key for the configuration entry.
/// This is an arbitrary key defined by the caller to indicate when the configuration should become active.
/// @param value The variable length byte configuration value.
function addConfigBytes(string memory name, uint256 activationKey, bytes memory value) external;
/// @notice Gets the number of checkpoints for a 32 byte configuration entry.
/// @param nameDigest The hash of the name of the configuration entry.
/// @return The number of checkpoints for the configuration entry.
function getNumCheckpointsBytes32(bytes32 nameDigest) external view returns (uint256);
/// @notice Gets the number of checkpoints for a variable length byte configuration entry.
/// @param nameDigest The hash of the name of the configuration entry.
/// @return The number of checkpoints for the configuration entry.
function getNumCheckpointsBytes(bytes32 nameDigest) external view returns (uint256);
/// @notice Gets the 32 byte configuration value at a specific index for a configuration entry.
/// @param nameDigest The hash of the name of the configuration entry.
/// @param index The index of the configuration value to retrieve.
/// @return The 32 byte configuration value at the specified index.
function getConfigBytes32(bytes32 nameDigest, uint256 index) external view returns (bytes32);
/// @notice Gets the variable length byte configuration value at a specific index for a configuration entry.
/// @param nameDigest The hash of the name of the configuration entry.
/// @param index The index of the configuration value to retrieve.
/// @return The variable length byte configuration value at the specified index.
function getConfigBytes(bytes32 nameDigest, uint256 index) external view returns (bytes memory);
/// @notice Gets the activation key for a 32 byte configuration entry at a specific index.
/// @param nameDigest The hash of the name of the configuration entry.
/// @param index The index of the configuration value to retrieve the activation key for.
/// @return The activation key at the specified index.
function getActivationKeyBytes32(bytes32 nameDigest, uint256 index) external view returns (uint256);
/// @notice Gets the activation key for a variable length byte configuration entry at a specific index.
/// @param nameDigest The hash of the name of the configuration entry.
/// @param index The index of the configuration value to retrieve the activation key for.
/// @return The activation key at the specified index.
function getActivationKeyBytes(bytes32 nameDigest, uint256 index) external view returns (uint256);
/// @notice Gets the full checkpoint (value and activation key) for a 32 byte configuration entry at a specific index.
/// @param nameDigest The hash of the name of the configuration entry.
/// @param index The index of the configuration value to retrieve the checkpoint for.
/// @return The full checkpoint (value and activation key) at the specified index.
function getCheckpointBytes32(bytes32 nameDigest, uint256 index)
external
view
returns (ConfigRegistryTypes.Bytes32Checkpoint memory);
/// @notice Gets the full checkpoint (value and activation key) for a variable length byte configuration entry at a specific index.
/// @param nameDigest The hash of the name of the configuration entry.
/// @param index The index of the configuration value to retrieve the checkpoint for.
/// @return The full checkpoint (value and activation key) at the specified index.
function getCheckpointBytes(bytes32 nameDigest, uint256 index)
external
view
returns (ConfigRegistryTypes.BytesCheckpoint memory);
/// @notice Gets the name of a 32 byte configuration entry by its name digest.
/// @param nameDigest The hash of the name of the configuration entry.
/// @return The name of the configuration entry.
function getConfigNameBytes32(bytes32 nameDigest) external view returns (string memory);
/// @notice Gets the name of a variable length byte configuration entry by its name digest.
/// @param nameDigest The hash of the name of the configuration entry.
/// @return The name of the configuration entry.
function getConfigNameBytes(bytes32 nameDigest) external view returns (string memory);
/// @notice Gets all names of 32 byte configuration entries.
/// @return An array of all configuration entry names.
function getAllConfigNamesBytes32() external view returns (string[] memory);
/// @notice Gets all names of variable length byte configuration entries.
/// @return An array of all configuration entry names.
function getAllConfigNamesBytes() external view returns (string[] memory);
}
/// @notice Interface for the EigenDA Directory
interface IEigenDADirectory is IEigenDAAddressDirectory, IEigenDAConfigRegistry {}
"
},
"lib/eigenlayer-middleware/src/interfaces/IIndexRegistry.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;
import {IRegistry} from "./IRegistry.sol";
/**
* @title Interface for a `Registry`-type contract that keeps track of an ordered list of operators for up to 256 quorums.
* @author Layr Labs, Inc.
*/
interface IIndexRegistry is IRegistry {
// EVENTS
// emitted when an operator's index in the ordered operator list for the quorum with number `quorumNumber` is updated
event QuorumIndexUpdate(bytes32 indexed operatorId, uint8 quorumNumber, uint32 newOperatorIndex);
// DATA STRUCTURES
// struct used to give definitive ordering to operators at each blockNumber.
struct OperatorUpdate {
// blockNumber number from which `operatorIndex` was the operators index
// the operator's index is the first entry such that `blockNumber >= entry.fromBlockNumber`
uint32 fromBlockNumber;
// the operator at this index
bytes32 operatorId;
}
// struct used to denote the number of operators in a quorum at a given blockNumber
struct QuorumUpdate {
// The total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber`
uint32 fromBlockNumber;
// The number of operators at `fromBlockNumber`
uint32 numOperators;
}
/**
* @notice Registers the operator with the specified `operatorId` for the quorums specified by `quorumNumbers`.
* @param operatorId is the id of the operator that is being registered
* @param quorumNumbers is the quorum numbers the operator is registered for
* @return numOperatorsPerQuorum is a list of the number of operators (including the registering operator) in each of the quorums the operator is registered for
* @dev access restricted to the RegistryCoordinator
* @dev Preconditions (these are assumed, not validated in this contract):
* 1) `quorumNumbers` has no duplicates
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already registered
*/
function registerOperator(bytes32 operatorId, bytes calldata quorumNumbers) external returns (uint32[] memory);
/**
* @notice Deregisters the operator with the specified `operatorId` for the quorums specified by `quorumNumbers`.
* @param operatorId is the id of the operator that is being deregistered
* @param quorumNumbers is the quorum numbers the operator is deregistered for
* @dev access restricted to the RegistryCoordinator
* @dev Preconditions (these are assumed, not validated in this contract):
* 1) `quorumNumbers` has no duplicates
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
*/
function deregisterOperator(bytes32 operatorId, bytes calldata quorumNumbers) external;
/**
* @notice Initialize a quorum by pushing its first quorum update
* @param quorumNumber The number of the new quorum
*/
function initializeQuorum(uint8 quorumNumber) external;
/// @notice Returns the OperatorUpdate entry for the specified `operatorIndex` and `quorumNumber` at the specified `arrayIndex`
function getOperatorUpdateAtIndex(uint8 quorumNumber, uint32 operatorIndex, uint32 arrayIndex)
external
view
returns (OperatorUpdate memory);
/// @notice Returns the QuorumUpdate entry for the specified `quorumNumber` at the specified `quorumIndex`
function getQuorumUpdateAtIndex(uint8 quorumNumber, uint32 quorumIndex)
external
view
returns (QuorumUpdate memory);
/// @notice Returns the most recent OperatorUpdate entry for the specified quorumNumber and operatorIndex
function getLatestOperatorUpdate(uint8 quorumNumber, uint32 operatorIndex)
external
view
returns (OperatorUpdate memory);
/// @notice Returns the most recent QuorumUpdate entry for the specified quorumNumber
function getLatestQuorumUpdate(uint8 quorumNumber) external view returns (QuorumUpdate memory);
/// @notice Returns the current number of operators of this service for `quorumNumber`.
function totalOperatorsForQuorum(uint8 quorumNumber) external view returns (uint32);
/// @notice Returns an ordered list of operators of the services for the given `quorumNumber` at the given `blockNumber`
function getOperatorListAtBlockNumber(uint8 quorumNumber, uint32 blockNumber)
external
view
returns (bytes32[] memory);
}
"
},
"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;
import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol";
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {IRegistry} from "./IRegistry.sol";
/**
* @title Interface for a `Registry` that keeps track of stakes of operators for up to 256 quorums.
* @author Layr Labs, Inc.
*/
interface IStakeRegistry is IRegistry {
// DATA STRUCTURES
/// @notice struct used to store the stakes of an individual operator or the sum of all operators' stakes, for storage
struct StakeUpdate {
// the block number at which the stake amounts were updated and stored
uint32 updateBlockNumber;
// the block number at which the *next update* occurred.
/// @notice This entry has the value **0** until another update takes place.
uint32 nextUpdateBlockNumber;
// stake weight for the quorum
uint96 stake;
}
/**
* @notice In weighing a particular strategy, the amount of underlying asset for that strategy is
* multiplied by its multiplier, then divided by WEIGHTING_DIVISOR
*/
struct StrategyParams {
IStrategy strategy;
uint96 multiplier;
}
// EVENTS
/// @notice emitted whenever the stake of `operator` is updated
event OperatorStakeUpdate(bytes32 indexed operatorId, uint8 quorumNumber, uint96 stake);
/// @notice emitted when the minimum stake for a quorum is updated
event MinimumStakeForQuorumUpdated(uint8 indexed quorumNumber, uint96 minimumStake);
/// @notice emitted when a new quorum is created
event QuorumCreated(uint8 indexed quorumNumber);
/// @notice emitted when `strategy` has been added to the array at `strategyParams[quorumNumber]`
event StrategyAddedToQuorum(uint8 indexed quorumNumber, IStrategy strategy);
/// @notice emitted when `strategy` has removed from the array at `strategyParams[quorumNumber]`
event StrategyRemovedFromQuorum(uint8 indexed quorumNumber, IStrategy strategy);
/// @notice emitted when `strategy` has its `multiplier` updated in the array at `strategyParams[quorumNumber]`
event StrategyMultiplierUpdated(uint8 indexed quorumNumber, IStrategy strategy, uint256 multiplier);
/**
* @notice Registers the `operator` with `operatorId` for the specified `quorumNumbers`.
* @param operator The address of the operator to register.
* @param operatorId The id of the operator to register.
* @param quorumNumbers The quorum numbers the operator is registering for, where each byte is an 8 bit integer quorumNumber.
* @return The operator's current stake for each quorum, and the total stake for each quorum
* @dev access restricted to the RegistryCoordinator
* @dev Preconditions (these are assumed, not validated in this contract):
* 1) `quorumNumbers` has no duplicates
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already registered
*/
function registerOperator(address operator, bytes32 operatorId, bytes memory quorumNumbers)
external
returns (uint96[] memory, uint96[] memory);
/**
* @notice Deregisters the operator with `operatorId` for the specified `quorumNumbers`.
* @param operatorId The id of the operator to deregister.
* @param quorumNumbers The quorum numbers the operator is deregistering from, where each byte is an 8 bit integer quorumNumber.
* @dev access restricted to the RegistryCoordinator
* @dev Preconditions (these are assumed, not validated in this contract):
* 1) `quorumNumbers` has no duplicates
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
*/
function deregisterOperator(bytes32 operatorId, bytes memory quorumNumbers) external;
/**
* @notice Initialize a new quorum created by the registry coordinator by setting strategies, weights, and minimum stake
*/
function initializeQuorum(uint8 quorumNumber, uint96 minimumStake, StrategyParams[] memory strategyParams)
external;
/// @notice Adds new strategies and the associated multipliers to the @param quorumNumber.
function addStrategies(uint8 quorumNumber, StrategyParams[] memory strategyParams) external;
/**
* @notice This function is used for removing strategies and their associated weights from the
* mapping strategyParams for a specific @param quorumNumber.
* @dev higher indices should be *first* in the list of @param indicesToRemove, since otherwise
* the removal of lower index entries will cause a shift in the indices of the other strategiesToRemove
*/
function removeStrategies(uint8 quorumNumber, uint256[] calldata indicesToRemove) external;
/**
* @notice This function is used for modifying the weights of strategies that are already in the
* mapping strategyParams for a specific
* @param quorumNumber is the quorum number to change the strategy for
* @param strategyIndices are the indices of the strategies to change
* @param newMultipliers are the new multipliers for the strategies
*/
function modifyStrategyParams(
uint8 quorumNumber,
uint256[] calldata strategyIndices,
uint96[] calldata newMultipliers
) external;
/// @notice Constant used as a divisor in calculating weights.
function WEIGHTING_DIVISOR() external pure returns (uint256);
/// @notice Returns the EigenLayer delegation manager contract.
function delegation() external view returns (IDelegationManager);
/// @notice In order to register for a quorum i, an operator must have at least `minimumStakeForQuorum[i]`
function minimumStakeForQuorum(uint8 quorumNumber) external view returns (uint96);
/// @notice Returns the length of the dynamic array stored in `strategyParams[quorumNumber]`.
function strategyParamsLength(uint8 quorumNumber) external view returns (uint256);
/// @notice Returns the strategy and weight multiplier for the `index`'th strategy in the quorum `quorumNumber`
function strategyParamsByIndex(uint8 quorumNumber, uint256 index) external view returns (StrategyParams memory);
/**
* @notice This function computes the total weight of the @param operator in the quorum @param quorumNumber.
* @dev reverts in the case that `quorumNumber` is greater than or equal to `quorumCount`
*/
function weightOfOperatorForQuorum(uint8 quorumNumber, address operator) external view returns (uint96);
/**
* @notice Returns the entire `operatorIdToStakeHistory[operatorId][quorumNumber]` array.
* @param operatorId The id of the operator of interest.
* @param quorumNumber The quorum number to get the stake for.
*/
function getStakeHistory(bytes32 operatorId, uint8 quorumNumber) external view returns (StakeUpdate[] memory);
function getTotalStakeHistoryLength(uint8 quorumNumber) external view returns (uint256);
/**
* @notice Returns the `index`-th entry in the dynamic array of total stake, `totalStakeHistory` for quorum `quorumNumber`.
* @param quorumNumber The quorum number to get the stake for.
* @param index Array index for lookup, within the dynamic array `totalStakeHistory[quorumNumber]`.
*/
function getTotalStakeUpdateAtIndex(uint8 quorumNumber, uint256 index) external view returns (StakeUpdate memory);
/// @notice Returns the indices of the operator stakes for the provided `quorumNumber` at the given `blockNumber`
function getStakeUpdateIndexAtBlockNumber(bytes32 operatorId, uint8 quorumNumber, uint32 blockNumber)
external
view
returns (uint32);
/// @notice Returns the indices of the total stakes for the provided `quorumNumbers` at the given `blockNumber`
function getTotalStakeIndicesAtBlockNumber(uint32 blockNumber, bytes calldata quorumNumbers)
external
view
returns (uint32[] memory);
/**
* @notice Returns the `index`-th entry in the `operatorIdToStakeHistory[operatorId][quorumNumber]` array.
* @param quorumNumber The quorum number to get the stake for.
* @param operatorId The id of the operator of interest.
* @param index Array index for lookup, within the dynamic array `operatorIdToStakeHistory[operatorId][quorumNumber]`.
* @dev Function will revert if `index` is out-of-bounds.
*/
function getStakeUpdateAtIndex(uint8 quorumNumber, bytes32 operatorId, uint256 index)
external
view
returns (StakeUpdate memory);
/**
* @notice Returns the most recent stake weight for the `operatorId` for a certain quorum
* @dev Function returns an StakeUpdate struct with **every entry equal to 0** in the event that the operator has no stake history
*/
function getLatestStakeUpdate(bytes32 operatorId, uint8 quorumNumber) external view returns (StakeUpdate memory);
/**
* @notice Returns the stake weight corresponding to `operatorId` for quorum `quorumNumber`, at the
* `index`-th entry in the `operatorIdToStakeHistory[operatorId][quorumNumber]` array if the entry
* corresponds to the operator's stake at `blockNumber`. Reverts otherwise.
* @param quorumNumber The quorum number to get the stake for.
* @param operatorId The id of the operator of interest.
* @param index Array index for lookup, within the dynamic array `operatorIdToStakeHistory[operatorId][quorumNumber]`.
* @param blockNumber Block number to make sure the stake is from.
* @dev Function will revert if `index` is out-of-bounds.
* @dev used the BLSSignatureChecker to get past stakes of signing operators
*/
function getStakeAtBlockNumberAndIndex(uint8 quorumNumber, uint32 blockNumber, bytes32 operatorId, uint256 index)
external
view
returns (uint96);
/**
* @notice Returns the total stake weight for quorum `quorumNumber`, at the `index`-th entry in the
* `totalStakeHistory[quorumNumber]` array if the entry corresponds to the total stake at `blockNumber`.
* Reverts otherwise.
* @param quorumNumber The quorum number to get the stake for.
* @param index Array index for lookup, within the dynamic array `totalStakeHistory[quorumNumber]`.
* @param blockNumber Block number to make sure the stake is from.
* @dev Function will revert if `index` is out-of-bounds.
* @dev used the BLSSignatureChecker to get past stakes of signing operators
*/
function getTotalStakeAtBlockNumberFromIndex(uint8 quorumNumber, uint32 blockNumber, uint256 index)
external
view
returns (uint96);
/**
* @notice Returns the most recent stake weight for the `operatorId` for quorum `quorumNumber`
* @dev Function returns weight of **0** in the event that the operator has no stake history
*/
function getCurrentStake(bytes32 operatorId, uint8 quorumNumber) external view returns (uint96);
/// @notice Returns the stake of the operator for the provided `quorumNumber` at the given `blockNumber`
function getStakeAtBlockNumber(bytes32 operatorId, uint8 quorumNumber, uint32 blockNumber)
external
view
returns (uint96);
/**
* @notice Returns the stake weight from the latest entry in `_totalStakeHistory` for quorum `quorumNumber`.
* @dev Will revert if `_totalStakeHistory[quorumNumber]` is empty.
*/
function getCurrentTotalStake(uint8 quorumNumber) external view returns (uint96);
/**
* @notice Called by the registry coordinator to update an operator's stake for one
* or more quorums.
*
* If the operator no longer has the minimum stake required for a quorum, they are
* added to the
* @return A bitmap of quorums where the operator no longer meets the minimum stake
* and should be deregistered.
*/
function updateOperatorStake(address operator, bytes32 operatorId, bytes calldata quorumNumbers)
external
returns (uint192);
}
"
},
"lib/eigenlayer-middleware/src/interfaces/IBLSApkRegistry.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;
import {IRegistry} from "./IRegistry.sol";
import {BN254} from "../libraries/BN254.sol";
/**
* @title Minimal interface for a registry that keeps track of aggregate operator public keys across many quorums.
* @author Layr Labs, Inc.
*/
interface IBLSApkRegistry is IRegistry {
// STRUCTS
/// @notice Data structure used to track the history of the Aggregate Public Key of all operators
struct ApkUpdate {
// first 24 bytes of keccak256(apk_x0, apk_x1, apk_y0, apk_y1)
bytes24 apkHash;
// block number at which the update occurred
uint32 updateBlockNumber;
// block number at which the next update occurred
uint32 nextUpdateBlockNumber;
}
/**
* @notice Struct used when registering a new public key
* @param pubkeyRegistrationSignature is the registration message signed by the private key of the operator
* @param pubkeyG1 is the corresponding G1 public key of the operator
* @param pubkeyG2 is the corresponding G2 public key of the operator
*/
struct PubkeyRegistrationParams {
BN254.G1Point pubkeyRegistrationSignature;
BN254.G1Point pubkeyG1;
BN254.G2Point pubkeyG2;
}
// EVENTS
/// @notice Emitted when `operator` registers with the public keys `pubkeyG1` and `pubkeyG2`.
event NewPubkeyRegistration(address indexed operator, BN254.G1Point pubkeyG1, BN254.G2Point pubkeyG2);
// @notice Emitted when a new operator pubkey is registered for a set of quorums
event OperatorAddedToQuorums(address operator, bytes32 operatorId, bytes quorumNumbers);
// @notice Emitted when an operator pubkey is removed from a set of quorums
event OperatorRemovedFromQuorums(address operator, bytes32 operatorId, bytes quorumNumbers);
/**
* @notice Registers the `operator`'s pubkey for the specified `quorumNumbers`.
* @param operator The address of the operator to register.
* @param quorumNumbers The quorum numbers the operator is registering for, where each byte is an 8 bit integer quorumNumber.
* @dev access restricted to the RegistryCoordinator
* @dev Preconditions (these are assumed, not validated in this contract):
* 1) `quorumNumbers` has no duplicates
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already registered
*/
function registerOperator(address operator, bytes calldata quorumNumbers) external;
/**
* @notice Deregisters the `operator`'s pubkey for the specified `quorumNumbers`.
* @param operator The address of the operator to deregister.
* @param quorumNumbers The quorum numbers the operator is deregistering from, where each byte is an 8 bit integer quorumNumber.
* @dev access restricted to the RegistryCoordinator
* @dev Preconditions (these are assumed, not validated in this contract):
* 1) `quorumNumbers` has no duplicates
* 2) `quorumNumbers.length` != 0
* 3) `quorumNumbers` is ordered in ascending order
* 4) the operator is not already deregistered
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for
*/
function deregisterOperator(address operator, bytes calldata quorumNumbers) external;
/**
* @notice Initializes a new quorum by pushing its first apk update
* @param quorumNumber The number of the new quorum
*/
function initializeQuorum(uint8 quorumNumber) external;
/**
* @notice mapping from operator address to pubkey hash.
* Returns *zero* if the `operator` has never registered, and otherwise returns the hash of the public key of the operator.
*/
function operatorToPubkeyHash(address operator) external view returns (bytes32);
/**
* @notice mapping from pubkey hash to operator address.
* Returns *zero* if no operator has ever registered the public key corresponding to `pubkeyHash`,
* and otherwise returns the (unique) registered operator who owns the BLS public key that is the preimage of `pubkeyHash`.
*/
function pubkeyHashToOperator(bytes32 pubkeyHash) external view returns (address);
/**
* @notice Called by the RegistryCoordinator register an operator as the owner of a BLS public key.
* @param operator is the operator for whom the key is being registered
* @param params contains the G1 & G2 public keys of the operator, and a signature proving their ownership
* @param pubkeyRegistrationMessageHash is a hash that the operator must sign to prove key ownership
*/
function registerBLSPublicKey(
address operator,
PubkeyRegistrationParams calldata params,
BN254.G1Point calldata pubkeyRegistrationMessageHash
) external returns (bytes32 operatorId);
/**
* @notice Returns the pubkey and pubkey hash of an operator
* @dev Reverts if the operator has not registered a valid pubkey
*/
function getRegisteredPubkey(address operator) external view returns (BN254.G1Point memory, bytes32);
/// @notice R
Submitted on: 2025-10-13 18:58:38
Comments
Log in to comment.
No comments yet.