Skip to content

Commit

Permalink
chore: unify StakeRegistry state variable typing, and split RegistryC…
Browse files Browse the repository at this point in the history
…oordinatorStorage into separate contract
  • Loading branch information
wadealexc committed Jan 11, 2024
1 parent da9e41f commit 6696d60
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 70 deletions.
79 changes: 15 additions & 64 deletions src/RegistryCoordinator.sol
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;

import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol";
import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";

import {EIP1271SignatureUtils} from "eigenlayer-contracts/src/contracts/libraries/EIP1271SignatureUtils.sol";
import {IPauserRegistry} from "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol";
import {Pausable} from "eigenlayer-contracts/src/contracts/permissions/Pausable.sol";

import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";
import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol";
import {IBLSApkRegistry} from "./interfaces/IBLSApkRegistry.sol";
import {ISocketUpdater} from "./interfaces/ISocketUpdater.sol";
import {IBLSApkRegistry} from "./interfaces/IBLSApkRegistry.sol";
import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol";
import {IIndexRegistry} from "./interfaces/IIndexRegistry.sol";
import {IServiceManager} from "./interfaces/IServiceManager.sol";
import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";

import {EIP1271SignatureUtils} from "eigenlayer-contracts/src/contracts/libraries/EIP1271SignatureUtils.sol";
import {BitmapUtils} from "./libraries/BitmapUtils.sol";
import {BN254} from "./libraries/BN254.sol";

import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol";
import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";

import {Pausable} from "eigenlayer-contracts/src/contracts/permissions/Pausable.sol";
import {RegistryCoordinatorStorage} from "./RegistryCoordinatorStorage.sol";

/**
* @title A `RegistryCoordinator` that has three registries:
* 1) a `StakeRegistry` that keeps track of operators' stakes
Expand All @@ -33,61 +34,13 @@ contract RegistryCoordinator is
Initializable,
Pausable,
OwnableUpgradeable,
IRegistryCoordinator,
RegistryCoordinatorStorage,
ISocketUpdater,
ISignatureUtils
{
using BitmapUtils for *;
using BN254 for BN254.G1Point;

/// @notice The EIP-712 typehash for the `DelegationApproval` struct used by the contract
bytes32 public constant OPERATOR_CHURN_APPROVAL_TYPEHASH =
keccak256("OperatorChurnApproval(bytes32 registeringOperatorId,OperatorKickParam[] operatorKickParams)OperatorKickParam(address operator,bytes32[] operatorIdsToSwap)");
/// @notice The EIP-712 typehash used for registering BLS public keys
bytes32 public constant PUBKEY_REGISTRATION_TYPEHASH = keccak256("BN254PubkeyRegistration(address operator)");
/// @notice The maximum value of a quorum bitmap
uint256 internal constant MAX_QUORUM_BITMAP = type(uint192).max;
/// @notice The basis point denominator
uint16 internal constant BIPS_DENOMINATOR = 10000;
/// @notice Index for flag that pauses operator registration
uint8 internal constant PAUSED_REGISTER_OPERATOR = 0;
/// @notice Index for flag that pauses operator deregistration
uint8 internal constant PAUSED_DEREGISTER_OPERATOR = 1;
/// @notice Index for flag pausing operator stake updates
uint8 internal constant PAUSED_UPDATE_OPERATOR = 2;
/// @notice The maximum number of quorums this contract supports
uint8 internal constant MAX_QUORUM_COUNT = 192;

/// @notice the ServiceManager for this AVS, which forwards calls onto EigenLayer's core contracts
IServiceManager public immutable serviceManager;
/// @notice the BLS Aggregate Pubkey Registry contract that will keep track of operators' aggregate BLS public keys per quorum
IBLSApkRegistry public immutable blsApkRegistry;
/// @notice the Stake Registry contract that will keep track of operators' stakes
IStakeRegistry public immutable stakeRegistry;
/// @notice the Index Registry contract that will keep track of operators' indexes
IIndexRegistry public immutable indexRegistry;

/// @notice the current number of quorums supported by the registry coordinator
uint8 public quorumCount;
/// @notice maps quorum number => operator cap and kick params
mapping(uint8 => OperatorSetParam) internal _quorumParams;
/// @notice maps operator id => historical quorums they registered for
mapping(bytes32 => QuorumBitmapUpdate[]) internal _operatorBitmapHistory;
/// @notice maps operator address => operator id and status
mapping(address => OperatorInfo) internal _operatorInfo;
/// @notice whether the salt has been used for an operator churn approval
mapping(bytes32 => bool) public isChurnApproverSaltUsed;
/// @notice mapping from quorum number to the latest block that all quorums were updated all at once
mapping(uint8 => uint256) public quorumUpdateBlockNumber;


/// @notice the dynamic-length array of the registries this coordinator is coordinating
address[] public registries;
/// @notice the address of the entity allowed to sign off on operators getting kicked out of the AVS during registration
address public churnApprover;
/// @notice the address of the entity allowed to eject operators from the AVS
address public ejector;

modifier onlyEjector {
require(msg.sender == ejector, "RegistryCoordinator.onlyEjector: caller is not the ejector");
_;
Expand All @@ -106,12 +59,10 @@ contract RegistryCoordinator is
IStakeRegistry _stakeRegistry,
IBLSApkRegistry _blsApkRegistry,
IIndexRegistry _indexRegistry
) EIP712("AVSRegistryCoordinator", "v0.0.1") {
serviceManager = _serviceManager;
stakeRegistry = _stakeRegistry;
blsApkRegistry = _blsApkRegistry;
indexRegistry = _indexRegistry;

)
RegistryCoordinatorStorage(_serviceManager, _stakeRegistry, _blsApkRegistry, _indexRegistry)
EIP712("AVSRegistryCoordinator", "v0.0.1")
{
_disableInitializers();
}

Expand Down
82 changes: 82 additions & 0 deletions src/RegistryCoordinatorStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;

import {IBLSApkRegistry} from "./interfaces/IBLSApkRegistry.sol";
import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol";
import {IIndexRegistry} from "./interfaces/IIndexRegistry.sol";
import {IServiceManager} from "./interfaces/IServiceManager.sol";
import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";

abstract contract RegistryCoordinatorStorage is IRegistryCoordinator {

/*******************************************************************************
CONSTANTS AND IMMUTABLES
*******************************************************************************/

/// @notice The EIP-712 typehash for the `DelegationApproval` struct used by the contract
bytes32 public constant OPERATOR_CHURN_APPROVAL_TYPEHASH =
keccak256("OperatorChurnApproval(bytes32 registeringOperatorId,OperatorKickParam[] operatorKickParams)OperatorKickParam(address operator,bytes32[] operatorIdsToSwap)");
/// @notice The EIP-712 typehash used for registering BLS public keys
bytes32 public constant PUBKEY_REGISTRATION_TYPEHASH = keccak256("BN254PubkeyRegistration(address operator)");
/// @notice The maximum value of a quorum bitmap
uint256 internal constant MAX_QUORUM_BITMAP = type(uint192).max;
/// @notice The basis point denominator
uint16 internal constant BIPS_DENOMINATOR = 10000;
/// @notice Index for flag that pauses operator registration
uint8 internal constant PAUSED_REGISTER_OPERATOR = 0;
/// @notice Index for flag that pauses operator deregistration
uint8 internal constant PAUSED_DEREGISTER_OPERATOR = 1;
/// @notice Index for flag pausing operator stake updates
uint8 internal constant PAUSED_UPDATE_OPERATOR = 2;
/// @notice The maximum number of quorums this contract supports
uint8 internal constant MAX_QUORUM_COUNT = 192;

/// @notice the ServiceManager for this AVS, which forwards calls onto EigenLayer's core contracts
IServiceManager public immutable serviceManager;
/// @notice the BLS Aggregate Pubkey Registry contract that will keep track of operators' aggregate BLS public keys per quorum
IBLSApkRegistry public immutable blsApkRegistry;
/// @notice the Stake Registry contract that will keep track of operators' stakes
IStakeRegistry public immutable stakeRegistry;
/// @notice the Index Registry contract that will keep track of operators' indexes
IIndexRegistry public immutable indexRegistry;

/*******************************************************************************
STATE
*******************************************************************************/

/// @notice the current number of quorums supported by the registry coordinator
uint8 public quorumCount;
/// @notice maps quorum number => operator cap and kick params
mapping(uint8 => OperatorSetParam) internal _quorumParams;
/// @notice maps operator id => historical quorums they registered for
mapping(bytes32 => QuorumBitmapUpdate[]) internal _operatorBitmapHistory;
/// @notice maps operator address => operator id and status
mapping(address => OperatorInfo) internal _operatorInfo;
/// @notice whether the salt has been used for an operator churn approval
mapping(bytes32 => bool) public isChurnApproverSaltUsed;
/// @notice mapping from quorum number to the latest block that all quorums were updated all at once
mapping(uint8 => uint256) public quorumUpdateBlockNumber;

/// @notice the dynamic-length array of the registries this coordinator is coordinating
address[] public registries;
/// @notice the address of the entity allowed to sign off on operators getting kicked out of the AVS during registration
address public churnApprover;
/// @notice the address of the entity allowed to eject operators from the AVS
address public ejector;

constructor(
IServiceManager _serviceManager,
IStakeRegistry _stakeRegistry,
IBLSApkRegistry _blsApkRegistry,
IIndexRegistry _indexRegistry
) {
serviceManager = _serviceManager;
stakeRegistry = _stakeRegistry;
blsApkRegistry = _blsApkRegistry;
indexRegistry = _indexRegistry;
}

// storage gap for upgradeability
// slither-disable-next-line shadowing-state
uint256[41] private __GAP;
}
8 changes: 4 additions & 4 deletions src/StakeRegistryStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ abstract contract StakeRegistryStorage is IStakeRegistry {

/// @notice In order to register for a quorum i, an operator must have at least `minimumStakeForQuorum[i]`
/// evaluated by this contract's 'VoteWeigher' logic.
uint96[256] public minimumStakeForQuorum;
mapping(uint8 => uint96) public minimumStakeForQuorum;

/// @notice array of the history of the total stakes for each quorum -- marked as internal since getTotalStakeFromIndex is a getter for this
StakeUpdate[][256] internal _totalStakeHistory;
/// @notice History of the total stakes for each quorum
mapping(uint8 => StakeUpdate[]) internal _totalStakeHistory;

/// @notice mapping from operator's operatorId to the history of their stake updates
mapping(bytes32 => mapping(uint8 => StakeUpdate[])) internal operatorStakeHistory;
Expand All @@ -53,5 +53,5 @@ abstract contract StakeRegistryStorage is IStakeRegistry {

// storage gap for upgradeability
// slither-disable-next-line shadowing-state
uint256[64] private __GAP;
uint256[46] private __GAP;
}
2 changes: 1 addition & 1 deletion src/interfaces/IStakeRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ interface IStakeRegistry is IRegistry {
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(uint256 quorumNumber) external view returns (uint96);
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);
Expand Down
2 changes: 1 addition & 1 deletion test/mocks/StakeRegistryMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ contract StakeRegistryMock is IStakeRegistry {
function strategyParamsLength(uint8 quorumNumber) external view returns (uint256) {}

/// @notice In order to register for a quorum i, an operator must have at least `minimumStakeForQuorum[i]`
function minimumStakeForQuorum(uint256 quorumNumber) external view returns (uint96) {}
function minimumStakeForQuorum(uint8 quorumNumber) external view returns (uint96) {}

/// @notice Returns the strategy and weight multiplier for the `index`'th strategy in the quorum `quorumNumber`
function strategyParamsByIndex(
Expand Down

0 comments on commit 6696d60

Please sign in to comment.