Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: repo cleanup #139

Merged
merged 5 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/BLSSignatureChecker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ contract BLSSignatureChecker is IBLSSignatureChecker {
bytes32
)
{
require(quorumNumbers.length != 0, "BLSSignatureChecker.checkSignatures: empty quorum input");

require(
(quorumNumbers.length == params.quorumApks.length) &&
(quorumNumbers.length == params.quorumApkIndices.length) &&
Expand Down
4 changes: 4 additions & 0 deletions src/IndexRegistryStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ abstract contract IndexRegistryStorage is Initializable, IIndexRegistry {
address public immutable registryCoordinator;

/// @notice maps quorumNumber => operator id => current operatorIndex
/// NOTE: This mapping is NOT updated when an operator is deregistered,
/// so it's possible that an index retrieved from this mapping is inaccurate.
/// If you're querying for an operator that might be deregistered, ALWAYS
/// check this index against the latest `_operatorIndexHistory` entry
mapping(uint8 => mapping(bytes32 => uint32)) public currentOperatorIndex;
/// @notice maps quorumNumber => operatorIndex => historical operator ids at that index
mapping(uint8 => mapping(uint32 => OperatorUpdate[])) internal _operatorIndexHistory;
Expand Down
291 changes: 165 additions & 126 deletions src/RegistryCoordinator.sol

Large diffs are not rendered by default.

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
6 changes: 4 additions & 2 deletions src/libraries/BitmapUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,16 @@ library BitmapUtils {
}

/**
* @notice Adds `a` and `b` using bitwise-or
* @notice Returns a new bitmap that contains all bits set in either `a` or `b`
* @dev Result is the union of `a` and `b`
*/
function plus(uint256 a, uint256 b) internal pure returns (uint256) {
return a | b;
}

/**
* @notice Subtracts `b` from `a` by negating `b` and using bitwise-and
* @notice Returns a new bitmap that clears all set bits of `b` from `a`
* @dev Negates `b` and returns the intersection of the result with `a`
*/
function minus(uint256 a, uint256 b) internal pure returns (uint256) {
return a & ~b;
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
21 changes: 21 additions & 0 deletions test/unit/BLSSignatureCheckerUnit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,25 @@ contract BLSSignatureCheckerUnitTests is BLSMockAVSDeployer {
nonSignerStakesAndSignature
);
}

function testBLSSignatureChecker_EmptyQuorums_Reverts(uint256 pseudoRandomNumber) public {
uint256 numNonSigners = pseudoRandomNumber % (maxOperatorsToRegister - 2) + 1;

uint256 quorumBitmap = 1;

(uint32 referenceBlockNumber, BLSSignatureChecker.NonSignerStakesAndSignature memory nonSignerStakesAndSignature) =
_registerSignatoriesAndGetNonSignerStakeAndSignatureRandom(pseudoRandomNumber, numNonSigners, quorumBitmap);

// Create an empty quorumNumbers array
bytes memory quorumNumbers = BitmapUtils.bitmapToBytesArray(0);

// expect a non-specific low-level revert, since this call will ultimately fail as part of the precompile call
cheats.expectRevert("BLSSignatureChecker.checkSignatures: empty quorum input");
blsSignatureChecker.checkSignatures(
msgHash,
quorumNumbers,
referenceBlockNumber,
nonSignerStakesAndSignature
);
}
}