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

feat: support multiple rollup chain IDs #138

Merged
merged 6 commits into from
May 17, 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
165 changes: 102 additions & 63 deletions contracts/src/core/MachServiceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
ZeroAddress,
AlreadyInAllowlist,
NotInAllowlist,
NoStatusChange,
InvalidRollupChainID,
InvalidReferenceBlockNum,
InsufficientThreshold,
InvalidStartIndex,
Expand Down Expand Up @@ -56,22 +58,36 @@ contract MachServiceManager is
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableSet for EnumerableSet.AddressSet;

/// @notice when applied to a function, ensures that the function is only callable by the `alertConfirmer`.
/**
* @dev Ensures that the function is only callable by the `alertConfirmer`.
*/
modifier onlyAlertConfirmer() {
if (_msgSender() != alertConfirmer) {
revert InvalidConfirmer();
}
_;
}

/// @notice when applied to a function, ensures that the function is only callable by the `whitelister`.
/**
* @dev Ensures that the function is only callable by the `whitelister`.
*/
modifier onlyWhitelister() {
if (_msgSender() != whitelister) {
revert NotWhitelister();
}
_;
}

/**
* @dev Ensures that the `rollupChainID` is valid.
*/
modifier onlyValidRollupChainID(uint256 rollupChainID) {
if (!rollupChainIDs[rollupChainID]) {
revert InvalidRollupChainID();
}
_;
}

constructor(
IAVSDirectory __avsDirectory,
IRegistryCoordinator __registryCoordinator,
Expand All @@ -84,18 +100,22 @@ contract MachServiceManager is
}

function initialize(
IPauserRegistry _pauserRegistry,
uint256 _initialPausedStatus,
address _initialOwner,
address _alertConfirmer,
address _whitelister,
uint256 _rollupChainId
IPauserRegistry pauserRegistry_,
uint256 initialPausedStatus_,
address initialOwner_,
address alertConfirmer_,
address whitelister_,
uint256[] calldata rollupChainIDs_
) public initializer {
_initializePauser(_pauserRegistry, _initialPausedStatus);
__ServiceManagerBase_init(_initialOwner);
_setAlertConfirmer(_alertConfirmer);
_setWhitelister(_whitelister);
_updateRollupChainId(_rollupChainId);
_initializePauser(pauserRegistry_, initialPausedStatus_);
__ServiceManagerBase_init(initialOwner_);
_setAlertConfirmer(alertConfirmer_);
_setWhitelister(whitelister_);

for (uint256 i; i < rollupChainIDs_.length; ++i) {
_setRollupChainID(rollupChainIDs_[i], true);
}

allowlistEnabled = true;
quorumThresholdPercentage = 66;
}
Expand All @@ -105,8 +125,7 @@ contract MachServiceManager is
//////////////////////////////////////////////////////////////////////////////

/**
* @notice Add an operator to the allowlist.
* @param operator The operator to add
* @inheritdoc IMachServiceManager
*/
function addToAllowlist(address operator) external onlyWhitelister {
if (operator == address(0)) {
Expand All @@ -120,8 +139,7 @@ contract MachServiceManager is
}

/**
* @notice Remove an operator from the allowlist.
* @param operator The operator to remove
* @inheritdoc IMachServiceManager
*/
function removeFromAllowlist(address operator) external onlyWhitelister {
if (!allowlist[operator]) {
Expand All @@ -132,7 +150,7 @@ contract MachServiceManager is
}

/**
* @notice Enable the allowlist.
* @inheritdoc IMachServiceManager
*/
function enableAllowlist() external onlyOwner {
if (allowlistEnabled) {
Expand All @@ -144,7 +162,7 @@ contract MachServiceManager is
}

/**
* @notice Disable the allowlist.
* @inheritdoc IMachServiceManager
*/
function disableAllowlist() external onlyOwner {
if (!allowlistEnabled) {
Expand All @@ -156,34 +174,43 @@ contract MachServiceManager is
}

/**
* @notice Set confirmer address.
* @inheritdoc IMachServiceManager
*/
function setConfirmer(address confirmer) external onlyOwner {
_setAlertConfirmer(confirmer);
}

/**
* @notice Set whitelister address.
* @inheritdoc IMachServiceManager
*/
function setWhitelister(address whitelister) external onlyOwner {
_setWhitelister(whitelister);
}

/**
* @notice Remove an Alert.
* @param messageHash The message hash of the alert
* @inheritdoc IMachServiceManager
*/
function removeAlert(bytes32 messageHash) external onlyOwner {
bool ret = _messageHashes.remove(messageHash);
function setRollupChainID(uint256 rollupChainId, bool status) external onlyOwner {
_setRollupChainID(rollupChainId, status);
}

/**
* @inheritdoc IMachServiceManager
*/
function removeAlert(uint256 rollupChainId, bytes32 messageHash)
external
onlyValidRollupChainID(rollupChainId)
onlyOwner
{
bool ret = _messageHashes[rollupChainId].remove(messageHash);
if (ret) {
_resolvedMessageHashes.add(messageHash);
_resolvedMessageHashes[rollupChainId].add(messageHash);
emit AlertRemoved(messageHash, _msgSender());
}
}

/**
* @notice Update quorum threshold percentage
* @param thresholdPercentage The new quorum threshold percentage
* @inheritdoc IMachServiceManager
*/
function updateQuorumThresholdPercentage(uint8 thresholdPercentage) external onlyOwner {
if (thresholdPercentage > 100) {
Expand All @@ -193,18 +220,12 @@ contract MachServiceManager is
emit QuorumThresholdPercentageChanged(thresholdPercentage);
}

function updateRollupChainId(uint256 newChainid) external onlyOwner {
_updateRollupChainId(newChainid);
}

//////////////////////////////////////////////////////////////////////////////
// Operator Registration //
//////////////////////////////////////////////////////////////////////////////

/**
* @notice Register an operator with the AVS. Forwards call to EigenLayer' AVSDirectory.
* @param operator The address of the operator to register.
* @param operatorSignature The signature, salt, and expiry of the operator's signature.
* @inheritdoc IServiceManager
*/
function registerOperatorToAVS(
address operator,
Expand All @@ -223,8 +244,7 @@ contract MachServiceManager is
}

/**
* @notice Deregister an operator from the AVS. Forwards a call to EigenLayer's AVSDirectory.
* @param operator The address of the operator to register.
* @inheritdoc IServiceManager
*/
function deregisterOperatorFromAVS(address operator)
public
Expand All @@ -242,22 +262,20 @@ contract MachServiceManager is
//////////////////////////////////////////////////////////////////////////////

/**
* @notice This function is used for
* - submitting alert,
* - check that the aggregate signature is valid,
* - and check whether quorum has been achieved or not.
* @inheritdoc IMachServiceManager
*/
function confirmAlert(
uint256 rollupChainId,
neutiyoo marked this conversation as resolved.
Show resolved Hide resolved
AlertHeader calldata alertHeader,
NonSignerStakesAndSignature memory nonSignerStakesAndSignature
) external whenNotPaused onlyAlertConfirmer {
) external whenNotPaused onlyAlertConfirmer onlyValidRollupChainID(rollupChainId) {
// make sure the information needed to derive the non-signers and batch is in calldata to avoid emitting events
if (tx.origin != msg.sender) {
revert InvalidSender();
}

// check is it is the resolved alert before
if (_resolvedMessageHashes.contains(alertHeader.messageHash)) {
if (_resolvedMessageHashes[rollupChainId].contains(alertHeader.messageHash)) {
revert ResolvedAlert();
}

Expand Down Expand Up @@ -301,7 +319,7 @@ contract MachServiceManager is
}

// store alert
bool success = _messageHashes.add(alertHeader.messageHash);
bool success = _messageHashes[rollupChainId].add(alertHeader.messageHash);
if (!success) {
revert AlreadyAdded();
}
Expand All @@ -313,19 +331,29 @@ contract MachServiceManager is
// View Functions //
//////////////////////////////////////////////////////////////////////////////

/// @notice Returns the length of total alerts
function totalAlerts() external view returns (uint256) {
return _messageHashes.length();
/**
* @inheritdoc IMachServiceManager
*/
function totalAlerts(uint256 rollupChainId) external view returns (uint256) {
return _messageHashes[rollupChainId].length();
}

/// @notice Checks if messageHash exists
function contains(bytes32 messageHash) external view returns (bool) {
return _messageHashes.contains(messageHash);
/**
* @inheritdoc IMachServiceManager
*/
function contains(uint256 rollupChainId, bytes32 messageHash) external view returns (bool) {
return _messageHashes[rollupChainId].contains(messageHash);
}

/// @notice Returns an array of messageHash
function queryMessageHashes(uint256 start, uint256 querySize) external view returns (bytes32[] memory) {
uint256 length = _messageHashes.length();
/**
* @inheritdoc IMachServiceManager
*/
function queryMessageHashes(uint256 rollupChainId, uint256 start, uint256 querySize)
external
view
returns (bytes32[] memory)
{
uint256 length = _messageHashes[rollupChainId].length();

if (start >= length) {
revert InvalidStartIndex();
Expand All @@ -339,7 +367,7 @@ contract MachServiceManager is

bytes32[] memory output = new bytes32[](end - start);
for (uint256 i = start; i < end; ++i) {
output[i - start] = _messageHashes.at(i);
output[i - start] = _messageHashes[rollupChainId].at(i);
}

return output;
Expand All @@ -349,29 +377,35 @@ contract MachServiceManager is
// Internal Functions //
//////////////////////////////////////////////////////////////////////////////

/// @notice hash the alert header
/**
* @dev Hashes an alert header
*/
function _hashAlertHeader(AlertHeader calldata alertHeader) internal pure returns (bytes32) {
return keccak256(abi.encode(_convertAlertHeaderToReducedAlertHeader(alertHeader)));
}

/// @notice changes the alert confirmer
/**
* @dev Changes the alert confirmer
*/
function _setAlertConfirmer(address _alertConfirmer) internal {
address previousBatchConfirmer = alertConfirmer;
alertConfirmer = _alertConfirmer;
emit AlertConfirmerChanged(previousBatchConfirmer, alertConfirmer);
}

/// @notice changes the whitelister
/**
* @dev Changes the whitelister
*/
function _setWhitelister(address _whitelister) internal {
address previousWhitelister = whitelister;
whitelister = _whitelister;
emit WhitelisterChanged(previousWhitelister, _whitelister);
}

/**
* @notice converts a alert header to a reduced alert header
* @dev Converts a alert header to a reduced alert header
* @param alertHeader the alert header to convert
*/

function _convertAlertHeaderToReducedAlertHeader(AlertHeader calldata alertHeader)
internal
pure
Expand All @@ -383,9 +417,14 @@ contract MachServiceManager is
});
}

function _updateRollupChainId(uint256 newChainid) internal {
uint256 previousRollupChainId = rollupChainId;
rollupChainId = newChainid;
emit RollupChainIdUpdated(previousRollupChainId, newChainid);
function _setRollupChainID(uint256 rollupChainId, bool status) internal {
if (rollupChainId < 1) {
revert InvalidRollupChainID();
}
if (rollupChainIDs[rollupChainId] == status) {
revert NoStatusChange();
}
rollupChainIDs[rollupChainId] = status;
emit RollupChainIDUpdated(rollupChainId, status);
}
}
19 changes: 15 additions & 4 deletions contracts/src/core/MachServiceManagerStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@ abstract contract MachServiceManagerStorage {
// CONSTANTS
uint256 public constant THRESHOLD_DENOMINATOR = 100;

EnumerableSet.Bytes32Set internal _messageHashes;
// Slot 0
mapping(uint256 => EnumerableSet.Bytes32Set) internal _messageHashes;

// Slot 1
/// @notice Ethereum addresses of currently register operators
EnumerableSet.AddressSet internal _operators;

// Slot 2
/// @notice Set of operators that are allowed to register
mapping(address => bool) public allowlist;

// Slot 3
/// @notice address that is permissioned to confirm alerts
address public alertConfirmer;

Expand All @@ -31,16 +35,23 @@ abstract contract MachServiceManagerStorage {
/// @notice Minimal quorum threshold percentage
uint8 public quorumThresholdPercentage;

// slot 4
/// @notice Resolved message hashes, prevent aggregator from replay any resolved alert
EnumerableSet.Bytes32Set internal _resolvedMessageHashes;
mapping(uint256 => EnumerableSet.Bytes32Set) internal _resolvedMessageHashes;

// slot 5
/// @notice Role for whitelisting operators
address public whitelister;

// slot 6
/// @notice Rollup chain id
uint256 public rollupChainId;
uint256 private __DEPRECATED_SLOT6; // rollupChainId

// slot 7
/// @notice Allowed rollup chain IDs
mapping(uint256 => bool) public rollupChainIDs;

// storage gap for upgradeability
// slither-disable-next-line shadowing-state
uint256[43] private __GAP;
uint256[42] private __GAP;
}
Loading