Skip to content

Commit

Permalink
comments
Browse files Browse the repository at this point in the history
  • Loading branch information
shaspitz committed Sep 17, 2024
1 parent 166e1c2 commit 84496df
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 14 deletions.
92 changes: 84 additions & 8 deletions contracts/contracts/interfaces/IMevCommitMiddleware.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity 0.8.26;

import {TimestampOccurrence} from "../utils/Occurrence.sol";
import {IRegistry} from "symbiotic-core/interfaces/common/IRegistry.sol";

interface IMevCommitMiddleware {

Expand Down Expand Up @@ -55,12 +56,10 @@ interface IMevCommitMiddleware {

/// @notice Emmitted when a validator record is added to state
/// @dev The position is one-indexed.
event ValRecordAdded(bytes blsPubkey, address indexed operator,
address indexed vault, uint256 indexed position);
event ValRecordAdded(bytes blsPubkey, address indexed operator, address indexed vault, uint256 indexed position);

/// @notice Emmitted when validator deregistration is requested
event ValidatorDeregistrationRequested(bytes blsPubkey, address indexed msgSender,
uint256 indexed position);
event ValidatorDeregistrationRequested(bytes blsPubkey, address indexed msgSender, uint256 indexed position);

/// @notice Emmitted when a validator record is deleted by the contract owner
event ValRecordDeleted(bytes blsPubkey, address indexed msgSender);
Expand All @@ -83,7 +82,7 @@ interface IMevCommitMiddleware {
/// @notice Emmitted when the slash period in seconds is set
event SlashPeriodSecondsSet(uint256 slashPeriodSeconds);

/// @notice Emmitted when the slash oracle is set
/// @notice Emmitted when the slash period in blocks is set
event SlashPeriodBlocksSet(uint256 slashPeriodBlocks);

/// @notice Emmitted when the slash oracle is set
Expand All @@ -95,8 +94,7 @@ interface IMevCommitMiddleware {

error InvalidArrayLengths(uint256 vaultLen, uint256 pubkeyLen);

error ValidatorsNotSlashable(address vault, address operator,
uint256 numRequested, uint256 potentialSlashableVals);
error ValidatorsNotSlashable(address vault, address operator, uint256 numRequested, uint256 potentialSlashableVals);

error MissingValRecord(bytes blsPubkey);

Expand Down Expand Up @@ -162,7 +160,85 @@ interface IMevCommitMiddleware {

error InvalidBLSPubKeyLength(uint256 expectedLength, uint256 actualLength);

/// @notice Checks if a validator is opted in.
function isValidatorOptedIn(bytes calldata blsPubkey) external view returns (bool);

// TODO: remaining functions
/// @notice Checks if a validator is slashable.
function isValidatorSlashable(bytes calldata blsPubkey) external view returns (bool);

/// @notice Returns the potential number of slashable validators for a given vault and operator.
function potentialSlashableValidators(address vault, address operator) external view returns (uint256);

/// @notice Checks if all validators for a given vault and operator are slashable.
function allValidatorsAreSlashable(address vault, address operator) external view returns (bool);

/// @notice Returns the one-indexed position of a blsPubkey in its valset.
/// @param blsPubkey The BLS public key of the validator.
/// @param vault The address of the vault.
/// @param operator The address of the operator.
/// @return The position in the valset or 0 if not present.
function getPositionInValset(bytes calldata blsPubkey, address vault, address operator) external view returns (uint256);

/// @notice Registers multiple operators.
function registerOperators(address[] calldata operators) external;

/// @notice Requests deregistration for multiple operators.
function requestOperatorDeregistrations(address[] calldata operators) external;

/// @notice Deregisters multiple operators.
function deregisterOperators(address[] calldata operators) external;

/// @notice Blacklists multiple operators.
function blacklistOperators(address[] calldata operators) external;

/// @notice Unblacklists multiple operators.
function unblacklistOperators(address[] calldata operators) external;

/// @notice Registers multiple vaults with corresponding slash amounts.
function registerVaults(address[] calldata vaults, uint256[] calldata slashAmounts) external;

/// @notice Updates slash amounts for multiple vaults.
function updateSlashAmounts(address[] calldata vaults, uint256[] calldata slashAmounts) external;

/// @notice Requests deregistration for multiple vaults.
function requestVaultDeregistrations(address[] calldata vaults) external;

/// @notice Deregisters multiple vaults.
function deregisterVaults(address[] calldata vaults) external;

/// @notice Registers validators via their BLS public key and vault which will secure them.
function registerValidators(bytes[][] calldata blsPubkeys, address[] calldata vaults) external;

/// @notice Requests deregistration for multiple validators.
function requestValDeregistrations(bytes[] calldata blsPubkeys) external;

/// @notice Deregisters multiple validators.
function deregisterValidators(bytes[] calldata blsPubkeys) external;

/// @notice Slashes multiple validators with their respective infraction timestamps.
function slashValidators(bytes[] calldata blsPubkeys, uint256[] calldata infractionTimestamps) external;

/// @notice Pauses the contract.
function pause() external;

/// @notice Unpauses the contract.
function unpause() external;

/// @notice Sets the network registry.
function setNetworkRegistry(IRegistry _networkRegistry) external;

/// @notice Sets the operator registry.
function setOperatorRegistry(IRegistry _operatorRegistry) external;

/// @notice Sets the vault factory.
function setVaultFactory(IRegistry _vaultFactory) external;

/// @notice Sets the network address.
function setNetwork(address _network) external;

/// @notice Sets the slash period in seconds.
function setSlashPeriodSeconds(uint256 slashPeriodSeconds_) external;

/// @notice Sets the slash oracle address.
function setSlashOracle(address slashOracle_) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Errors} from "../../utils/Errors.sol";
import {IVetoSlasher} from "symbiotic-core/interfaces/slasher/IVetoSlasher.sol";

/// @notice This contracts serve as an entrypoint for L1 validators
/// to *opt-in* to mev-commit, ie. attest to the rules of mev-commit,
/// at the risk of funds being slashed.
contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage,
Ownable2StepUpgradeable, PausableUpgradeable, UUPSUpgradeable {

using EnumerableSet for EnumerableSet.BytesSet;

/// @notice Only the slash oracle account can call functions marked with this modifier.
modifier onlySlashOracle() {
require(msg.sender == slashOracle, OnlySlashOracle(slashOracle));
_;
Expand All @@ -50,6 +54,14 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
_disableInitializers();
}

/// @notice Initializes the middleware contract.
/// @param _networkRegistry Symbiotic core network registry contract.
/// @param _operatorRegistry Symbiotic core operator registry contract.
/// @param _vaultFactory Symbiotic core vault factory contract.
/// @param _network Address of the mev-commit network EOA.
/// @param _slashPeriodSeconds Oracle slashing must be invoked within `slashPeriodSeconds` of any event causing a validator to transition from *opted-in* to **not** *opted-in*.
/// @param _slashOracle Address of the mev-commit oracle.
/// @param _owner Contract owner address.
function initialize(
IRegistry _networkRegistry,
IRegistry _operatorRegistry,
Expand Down Expand Up @@ -80,41 +92,54 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
revert Errors.InvalidFallback();
}

/// @notice Register operators, restricted to contract owner.
/// @param operators Addresses of the operators to register.
function registerOperators(address[] calldata operators) external onlyOwner {
uint256 len = operators.length;
for (uint256 i = 0; i < len; ++i) {
_registerOperator(operators[i]);
}
}

/// @notice Request operator deregistrations, restricted to contract owner.
/// @param operators Addresses of the operators to request deregistrations for.
function requestOperatorDeregistrations(address[] calldata operators) external onlyOwner {
uint256 len = operators.length;
for (uint256 i = 0; i < len; ++i) {
_requestOperatorDeregistration(operators[i]);
}
}

/// @notice Deregisters operators, restricted to contract owner.
/// @param operators Addresses of the operators to deregister.
function deregisterOperators(address[] calldata operators) external onlyOwner {
uint256 len = operators.length;
for (uint256 i = 0; i < len; ++i) {
_deregisterOperator(operators[i]);
}
}

/// @notice Blacklists operators, restricted to contract owner.
/// @param operators Addresses of the operators to blacklist.
function blacklistOperators(address[] calldata operators) external onlyOwner {
uint256 len = operators.length;
for (uint256 i = 0; i < len; ++i) {
_blacklistOperator(operators[i]);
}
}

/// @notice Unblacklists operators, restricted to contract owner.
/// @param operators Addresses of the operators to unblacklist.
function unblacklistOperators(address[] calldata operators) external onlyOwner {
uint256 len = operators.length;
for (uint256 i = 0; i < len; ++i) {
_unblacklistOperator(operators[i]);
}
}

/// @notice Registers vaults, restricted to contract owner.
/// @param vaults Addresses of the vaults to register.
/// @param slashAmounts Corresponding slash amounts for each vault.
function registerVaults(address[] calldata vaults, uint256[] calldata slashAmounts) external onlyOwner {
uint256 vLen = vaults.length;
require(vLen == slashAmounts.length, InvalidArrayLengths(vLen, slashAmounts.length));
Expand All @@ -123,6 +148,9 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
}
}

/// @notice Updates the slash amounts for vaults, restricted to contract owner.
/// @param vaults Addresses of the vaults to update.
/// @param slashAmounts Corresponding slash amounts for each vault.
function updateSlashAmounts(address[] calldata vaults, uint256[] calldata slashAmounts) external onlyOwner {
uint256 vLen = vaults.length;
require(vLen == slashAmounts.length, InvalidArrayLengths(vLen, slashAmounts.length));
Expand All @@ -131,20 +159,28 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
}
}

/// @notice Requests vault deregistrations, restricted to contract owner.
/// @param vaults Addresses of the vaults to request deregistrations for.
function requestVaultDeregistrations(address[] calldata vaults) external onlyOwner {
uint256 len = vaults.length;
for (uint256 i = 0; i < len; ++i) {
_requestVaultDeregistration(vaults[i]);
}
}

/// @notice Deregisters vaults, restricted to contract owner.
/// @param vaults Addresses of the vaults to deregister.
function deregisterVaults(address[] calldata vaults) external onlyOwner {
uint256 len = vaults.length;
for (uint256 i = 0; i < len; ++i) {
_deregisterVault(vaults[i]);
}
}

/// @notice Registers validators via their BLS public key and vault which will secure them.
/// @dev This function is callable by any delegated operator on behalf of a vault.
/// @param blsPubkeys BLS public keys of the validators to register.
/// @param vaults Addresses of vaults which will secure groups of validators.
function registerValidators(bytes[][] calldata blsPubkeys,
address[] calldata vaults) external whenNotPaused onlyValidBLSPubKeys(blsPubkeys) {
uint256 vaultLen = vaults.length;
Expand All @@ -164,6 +200,9 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
}
}

/// @notice Requests deregistrations for validators, restricted to contract owner,
/// or the (still registered and non-blacklisted) operator of the validator pubkey.
/// @param blsPubkeys BLS public keys of the validators to request deregistrations for.
function requestValDeregistrations(bytes[] calldata blsPubkeys) external whenNotPaused {
uint256 len = blsPubkeys.length;
for (uint256 i = 0; i < len; ++i) {
Expand Down Expand Up @@ -228,10 +267,12 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
_setSlashOracle(slashOracle_);
}

/// @notice Queries if a validator is opted-in to mev-commit through a vault.
function isValidatorOptedIn(bytes calldata blsPubkey) external view returns (bool) {
return _isValidatorOptedIn(blsPubkey);
}

/// @notice Queries if a validator is slashable.
function isValidatorSlashable(bytes calldata blsPubkey) external view returns (bool) {
ValidatorRecord storage record = validatorRecords[blsPubkey];
require(record.exists, MissingValRecord(blsPubkey));
Expand All @@ -240,15 +281,17 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
return _isValidatorSlashable(blsPubkey, record.vault, record.operator);
}

/// @notice Queries the number of potential slashable validators for a vault and operator.
function potentialSlashableValidators(address vault, address operator) external view returns (uint256) {
return _potentialSlashableVals(vault, operator);
}

/// @notice Queries if all validators for a vault and operator are slashable.
function allValidatorsAreSlashable(address vault, address operator) external view returns (bool) {
return _allValidatorsAreSlashable(vault, operator);
}

/// @dev Returns the one-indexed position of the blsPubkey in the valset.
/// @notice Queries the one-indexed position of a validator's BLS pubkey in its valset.
/// @return 0 if the blsPubkey is not in the valset.
function getPositionInValset(bytes calldata blsPubkey, address vault, address operator) external view returns (uint256) {
return _getPositionInValset(blsPubkey, vault, operator);
Expand Down Expand Up @@ -475,6 +518,7 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
emit OperatorRegistrySet(address(_operatorRegistry));
}

/// @dev Internal function to set the vault factory.
function _setVaultFactory(IRegistry _vaultFactory) internal {
require(_vaultFactory != IRegistry(address(0)), ZeroAddressNotAllowed());
vaultFactory = _vaultFactory;
Expand Down Expand Up @@ -553,29 +597,28 @@ contract MevCommitMiddleware is IMevCommitMiddleware, MevCommitMiddlewareStorage
return Subnetwork.subnetwork(network, SUBNETWORK_ID);
}

function _getSlashableVals(address vault, address operator) internal view returns (uint256) {
function _getNumSlashableVals(address vault, address operator) internal view returns (uint256) {
IBaseDelegator delegator = IBaseDelegator(IVault(vault).delegator());
uint256 allocatedStake = delegator.stake(_getSubnetwork(), operator);
uint256 slashAmount = vaultRecords[vault].slashAmount;
return allocatedStake / slashAmount;
}

// TODO: need to unit test
function _allValidatorsAreSlashable(address vault, address operator) internal view returns (bool) {
uint256 slashableVals = _getSlashableVals(vault, operator);
uint256 slashableVals = _getNumSlashableVals(vault, operator);
uint256 numVals = _vaultAndOperatorToValset[vault][operator].length();
return slashableVals >= numVals;
}

function _isValidatorSlashable(bytes calldata blsPubkey, address vault, address operator) internal view returns (bool) {
uint256 slashableVals = _getSlashableVals(vault, operator);
uint256 slashableVals = _getNumSlashableVals(vault, operator);
uint256 position = _getPositionInValset(blsPubkey, vault, operator);
require(position != 0, ValidatorNotInValset(blsPubkey, vault, operator));
return position <= slashableVals; // position is 1-indexed
}

function _potentialSlashableVals(address vault, address operator) internal view returns (uint256) {
uint256 slashableVals = _getSlashableVals(vault, operator);
uint256 slashableVals = _getNumSlashableVals(vault, operator);
uint256 alreadyRegistered = _vaultAndOperatorToValset[vault][operator].length();
if (slashableVals < alreadyRegistered) {
return 0;
Expand Down

0 comments on commit 84496df

Please sign in to comment.