Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
91c5a53
chore: bump to slashing branch
stevennevins Sep 30, 2024
9eb3446
chore: bump compiler version
stevennevins Sep 30, 2024
e579e21
fix: dep interface changes
stevennevins Sep 30, 2024
9e5e15f
fix: compiler errors from interface changes and type changes
stevennevins Oct 3, 2024
6068036
fix: compiler errors
stevennevins Oct 8, 2024
eea938a
chore: bump dependencies
stevennevins Oct 8, 2024
221b4fe
chore: bump core dependency and resolve issues
stevennevins Oct 8, 2024
b70945a
chore: bump core dependency and fix compiler errors
stevennevins Oct 10, 2024
2c80944
feat: integrate AllocationManager
stevennevins Oct 10, 2024
860faa8
feat: add a slashing permission to the service manager
stevennevins Oct 10, 2024
dad3d4d
chore: remove unneeded casting
stevennevins Oct 10, 2024
c8a8e16
feat: implement a slasher permission and forward call to AllocationMa…
stevennevins Oct 10, 2024
9d5c200
feat: add simiple slasher starting point
stevennevins Oct 10, 2024
ac12473
feat: slashers
stevennevins Oct 16, 2024
8caf960
chore: change around slashed event
stevennevins Oct 16, 2024
dd31230
fix: call dm
stevennevins Oct 21, 2024
e08cc44
fix: resolve merge conflict in dep
stevennevins Oct 21, 2024
fc2a1ba
feat: add proposal mechanism for updating slasher
stevennevins Oct 21, 2024
0fcee61
fix: set to completed instead of delete
stevennevins Oct 21, 2024
337d561
chore: use struct instead of params directly
stevennevins Oct 21, 2024
eb22245
chore: clean up params more
stevennevins Oct 21, 2024
4c60219
chore: simplify and organize files
stevennevins Oct 23, 2024
fcff338
chore: cleanup logic and couple event with internal func
stevennevins Oct 23, 2024
7213174
fix: pass correct params
stevennevins Oct 23, 2024
38dca52
chore: organize and add interface
stevennevins Oct 23, 2024
0847612
chore: nits
stevennevins Oct 23, 2024
825b82b
chore: cleanup more nits
stevennevins Oct 23, 2024
31dd3f3
fix: storage gap
stevennevins Oct 23, 2024
c287af6
chore: nits refactor
stevennevins Oct 23, 2024
999b2c0
chore: go back to fulfill being onlySlasher
stevennevins Oct 23, 2024
7ce35e1
test: fixes from core updates
stevennevins Oct 29, 2024
fdff6f2
fix: use delegated stake per operator set instead of per AVS
stevennevins Oct 30, 2024
a102f9f
fix: update to 14 days
stevennevins Nov 1, 2024
9af73b9
feat: configurable lookahead and stake type
stevennevins Nov 1, 2024
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: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ optimizer_runs = 200
# Whether or not to use the Yul intermediate representation compilation pipeline
via_ir = false
# Override the Solidity version (this overrides `auto_detect_solc`)
solc_version = '0.8.12'
solc_version = '0.8.27'

[etherscan]
mainnet = { key = "${ETHERSCAN_API_KEY}" }
Expand Down
2 changes: 1 addition & 1 deletion lib/eigenlayer-contracts
7 changes: 5 additions & 2 deletions script/OperatorSetUpgrade.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {IBLSApkRegistry} from "../src/interfaces/IBLSApkRegistry.sol";
import {IIndexRegistry} from "../src/interfaces/IIndexRegistry.sol";
import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol";
interface IServiceManagerMigration {
function getOperatorsToMigrate()
Expand Down Expand Up @@ -46,6 +47,7 @@ contract OperatorSetUpgradeScript is Script {
address public delegationManager;
address public blsApkRegistry;
address public indexRegistry;
address public allocationManager;

function setUp() public {
vm.label(DEFAULT_FORGE_SENDER, "DEFAULT FORGE SENDER");
Expand Down Expand Up @@ -145,7 +147,7 @@ contract OperatorSetUpgradeScript is Script {
function _upgradeAvsDirectory() internal {
address proxyAdmin = OperatorSetUpgradeLib.getAdmin(avsDirectory);
address avsDirectoryOwner = Ownable(proxyAdmin).owner();
AVSDirectory avsDirectoryImpl = new AVSDirectory(IDelegationManager(delegationManager));
AVSDirectory avsDirectoryImpl = new AVSDirectory(IDelegationManager(delegationManager), 0); // TODO: config

vm.startPrank(avsDirectoryOwner);
OperatorSetUpgradeLib.upgrade(avsDirectory, address(avsDirectoryImpl));
Expand Down Expand Up @@ -211,7 +213,8 @@ contract OperatorSetUpgradeScript is Script {
IAVSDirectory(avsDirectory),
IRewardsCoordinator(rewardsCoordinator),
IRegistryCoordinator(registryCoordinator),
IStakeRegistry(stakeRegistry)
IStakeRegistry(stakeRegistry),
IAllocationManager(allocationManager)
));
address newRegistryCoordinatorImpl = address(new RegistryCoordinator(
IServiceManager(serviceManager),
Expand Down
8 changes: 5 additions & 3 deletions src/BLSSignatureChecker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,11 @@ contract BLSSignatureChecker is IBLSSignatureChecker {
*/
{
bool _staleStakesForbidden = staleStakesForbidden;
uint256 withdrawalDelayBlocks = _staleStakesForbidden
? delegation.minWithdrawalDelayBlocks()
: 0;
/// TODO: FIX
uint256 withdrawalDelayBlocks = 0;
// uint256 withdrawalDelayBlocks = _staleStakesForbidden
// ? delegation.minWithdrawalDelayBlocks()
// : 0;

for (uint256 i = 0; i < quorumNumbers.length; i++) {
// If we're disallowing stale stake updates, check that each quorum's last update block
Expand Down
6 changes: 3 additions & 3 deletions src/RegistryCoordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.12;

import {IPauserRegistry} from "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol";
import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol";
import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {IAVSDirectory, OperatorSet} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {ISocketUpdater} from "./interfaces/ISocketUpdater.sol";
import {IBLSApkRegistry} from "./interfaces/IBLSApkRegistry.sol";
import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol";
Expand Down Expand Up @@ -676,7 +676,7 @@ contract RegistryCoordinator is
for (uint256 i = 0; i < quorumBytes.length; i++) {
/// We need to track forceDeregistrations so we don't pass an id that was already deregistered on the AVSDirectory
/// but hasnt yet been recorded in the middleware contracts
if (!avsDirectory.isMember(operator, IAVSDirectory.OperatorSet(address(serviceManager), uint8(quorumBytes[i])))){
if (!avsDirectory.isMember(operator, OperatorSet(address(serviceManager), uint8(quorumBytes[i])))){
forceDeregistrationCount++;
}
operatorSetIds[i] = uint8(quorumBytes[i]);
Expand All @@ -687,7 +687,7 @@ contract RegistryCoordinator is
uint32[] memory filteredOperatorSetIds = new uint32[](operatorSetIds.length - forceDeregistrationCount);
uint256 offset;
for (uint256 i; i < operatorSetIds.length; i++){
if (avsDirectory.isMember(operator, IAVSDirectory.OperatorSet(address(serviceManager), operatorSetIds[i]))){
if (avsDirectory.isMember(operator, OperatorSet(address(serviceManager), operatorSetIds[i]))){
filteredOperatorSetIds[i] = operatorSetIds[i+offset];
} else {
offset++;
Expand Down
53 changes: 45 additions & 8 deletions src/ServiceManagerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISi
import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {IRewardsCoordinator} from
"eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";

import {ServiceManagerBaseStorage} from "./ServiceManagerBaseStorage.sol";
import {IServiceManager} from "./interfaces/IServiceManager.sol";
Expand Down Expand Up @@ -38,36 +39,39 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
_;
}

function _checkRewardsInitiator() internal view {
require(
msg.sender == rewardsInitiator,
"ServiceManagerBase.onlyRewardsInitiator: caller is not the rewards initiator"
);
/// @notice only slasher can call functions with this modifier
modifier onlySlasher() {
_checkSlasher();
_;
}

/// @notice Sets the (immutable) `_registryCoordinator` address
constructor(
IAVSDirectory __avsDirectory,
IRewardsCoordinator __rewardsCoordinator,
IRegistryCoordinator __registryCoordinator,
IStakeRegistry __stakeRegistry
IStakeRegistry __stakeRegistry,
IAllocationManager __allocationManager
)
ServiceManagerBaseStorage(
__avsDirectory,
__rewardsCoordinator,
__registryCoordinator,
__stakeRegistry
__stakeRegistry,
__allocationManager
)
{
_disableInitializers();
}

function __ServiceManagerBase_init(
address initialOwner,
address _rewardsInitiator
address _rewardsInitiator,
address _slasher
) internal virtual onlyInitializing {
_transferOwnership(initialOwner);
_setRewardsInitiator(_rewardsInitiator);
_setSlasher(_slasher);
}

/**
Expand All @@ -79,6 +83,10 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
_avsDirectory.updateAVSMetadataURI(_metadataURI);
}

function slashOperator(IAllocationManager.SlashingParams memory params) external onlySlasher {
_allocationManager.slashOperator(params);
}

/**
* @notice Creates a new rewards submission to the EigenLayer RewardsCoordinator contract, to be split amongst the
* set of stakers delegated to operators who are registered to this `avs`
Expand Down Expand Up @@ -168,6 +176,15 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
_setRewardsInitiator(newRewardsInitiator);
}

/**
* @notice Sets the slasher address
* @param newSlasher The new slasher address
* @dev only callable by the owner
*/
function setSlasher(address newSlasher) external onlyOwner {
_setSlasher(newSlasher);
}

/**
* @notice Migrates the AVS to use operator sets and creates new operator set IDs.
* @param operatorSetsToCreate An array of operator set IDs to create.
Expand Down Expand Up @@ -325,6 +342,11 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
rewardsInitiator = newRewardsInitiator;
}

function _setSlasher(address newSlasher) internal {
emit SlasherUpdated(slasher, newSlasher);
slasher = newSlasher;
}

/**
* @notice Returns the list of strategies that the AVS supports for restaking
* @dev This function is intended to be called off-chain
Expand Down Expand Up @@ -402,4 +424,19 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
function avsDirectory() external view override returns (address) {
return address(_avsDirectory);
}

function _checkRewardsInitiator() internal view {
require(
msg.sender == rewardsInitiator,
"ServiceManagerBase.onlyRewardsInitiator: caller is not the rewards initiator"
);
}


function _checkSlasher() internal view {
require(
msg.sender == slasher,
"ServiceManagerBase.onlySlasher: caller is not the slasher"
);
}
}
13 changes: 10 additions & 3 deletions src/ServiceManagerBaseStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol";

import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";

/**
* @title Storage variables for the `ServiceManagerBase` contract.
Expand All @@ -25,6 +26,7 @@ abstract contract ServiceManagerBaseStorage is IServiceManager, OwnableUpgradeab
IRewardsCoordinator internal immutable _rewardsCoordinator;
IRegistryCoordinator internal immutable _registryCoordinator;
IStakeRegistry internal immutable _stakeRegistry;
IAllocationManager internal immutable _allocationManager;

/**
*
Expand All @@ -35,21 +37,26 @@ abstract contract ServiceManagerBaseStorage is IServiceManager, OwnableUpgradeab
/// @notice The address of the entity that can initiate rewards
address public rewardsInitiator;

/// @notice The address of the slasher account
address public slasher;

bool public migrationFinalized;

/// @notice Sets the (immutable) `_avsDirectory`, `_rewardsCoordinator`, `_registryCoordinator`, and `_stakeRegistry` addresses
/// @notice Sets the (immutable) `_avsDirectory`, `_rewardsCoordinator`, `_registryCoordinator`, `_stakeRegistry`, and `_allocationManager` addresses
constructor(
IAVSDirectory __avsDirectory,
IRewardsCoordinator __rewardsCoordinator,
IRegistryCoordinator __registryCoordinator,
IStakeRegistry __stakeRegistry
IStakeRegistry __stakeRegistry,
IAllocationManager __allocationManager
) {
_avsDirectory = __avsDirectory;
_rewardsCoordinator = __rewardsCoordinator;
_registryCoordinator = __registryCoordinator;
_stakeRegistry = __stakeRegistry;
_allocationManager = __allocationManager;
}

// storage gap for upgradeability
uint256[49] private __GAP;
uint256[48] private __GAP;
}
7 changes: 4 additions & 3 deletions src/StakeRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.12;

import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol";
import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {IAVSDirectory, OperatorSet} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {IServiceManager} from "./interfaces/IServiceManager.sol";

import {StakeRegistryStorage, IStrategy} from "./StakeRegistryStorage.sol";
Expand Down Expand Up @@ -182,7 +182,7 @@ contract StakeRegistry is StakeRegistryStorage {
// Query the AVSDirectory to check if the operator is directly unregistered
operatorRegistered = avsDirectory.isMember(
operator,
IAVSDirectory.OperatorSet(address(serviceManager), operatorSetId)
OperatorSet(address(serviceManager), operatorSetId)
);

if (!hasMinimumStake || (isOperatorSetAVS && !operatorRegistered)) {
Expand Down Expand Up @@ -491,7 +491,8 @@ contract StakeRegistry is StakeRegistryStorage {
uint256 stratsLength = strategyParamsLength(quorumNumber);
StrategyParams memory strategyAndMultiplier;

uint256[] memory strategyShares = delegation.getOperatorShares(operator, strategiesPerQuorum[quorumNumber]);
uint256[] memory strategyShares;
// = delegation.getDelegatableShares(operator, strategiesPerQuorum[quorumNumber]);
for (uint256 i = 0; i < stratsLength; i++) {
// accessing i^th StrategyParams struct for the quorumNumber
strategyAndMultiplier = strategyParams[quorumNumber][i];
Expand Down
6 changes: 5 additions & 1 deletion src/interfaces/IServiceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity >=0.5.0;
import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {IServiceManagerUI} from "./IServiceManagerUI.sol";
import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol";
import {IAllocationManagerTypes} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";

/**
* @title Minimal interface for a ServiceManager-type contract that forms the single point for an AVS to push updates to EigenLayer
Expand All @@ -23,7 +24,7 @@ interface IServiceManager is IServiceManagerUI {
*/
function createAVSRewardsSubmission(IRewardsCoordinator.RewardsSubmission[] calldata rewardsSubmissions) external;

function createOperatorSets(uint32[] memory operatorSetIds) external ;
function createOperatorSets(uint32[] memory operatorSetIds) external;

/**
* @notice Forwards a call to EigenLayer's AVSDirectory contract to register an operator to operator sets
Expand All @@ -44,6 +45,9 @@ interface IServiceManager is IServiceManagerUI {
*/
function deregisterOperatorFromOperatorSets(address operator, uint32[] calldata operatorSetIds) external;

function slashOperator(IAllocationManagerTypes.SlashingParams memory params) external;

// EVENTS
event RewardsInitiatorUpdated(address prevRewardsInitiator, address newRewardsInitiator);
event SlasherUpdated(address prevSlasher, address newSlasher);
}
9 changes: 6 additions & 3 deletions src/libraries/SignatureCheckerLib.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;

import {EIP1271SignatureUtils} from
"eigenlayer-contracts/src/contracts/libraries/EIP1271SignatureUtils.sol";
import "@openzeppelin-upgrades/contracts/utils/cryptography/SignatureCheckerUpgradeable.sol";

/**
* @title SignatureCheckerLib
Expand All @@ -11,6 +10,8 @@ import {EIP1271SignatureUtils} from
* validation logic to this external library.
*/
library SignatureCheckerLib {
error InvalidSignature();

/**
* @notice Validates a signature using EIP-1271 standard.
* @param signer The address of the signer.
Expand All @@ -22,6 +23,8 @@ library SignatureCheckerLib {
bytes32 digestHash,
bytes memory signature
) external view {
EIP1271SignatureUtils.checkSignature_EIP1271(signer, digestHash, signature);
if (!SignatureCheckerUpgradeable.isValidSignatureNow(signer, digestHash, signature)) {
Copy link
Contributor

@gpsanant gpsanant Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use require syntax with new solc version

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah lets bump to 0.8.27

revert InvalidSignature();
}
}
}
31 changes: 31 additions & 0 deletions src/slashers/Slasher.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;

import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {SlasherBase} from "./SlasherBase.sol";

contract Slasher is SlasherBase {
uint256 public nextRequestId;

function initialize(address _serviceManager) public initializer {
__SlasherBase_init(_serviceManager);
}

function fulfillSlashingRequest(
address operator,
uint32 operatorSetId,
IStrategy[] memory strategies,
uint256 wadToSlash,
string memory description
) external virtual {
uint256 requestId = nextRequestId++;
_fulfillSlashingRequest(
operator,
operatorSetId,
strategies,
wadToSlash,
description
);
emit OperatorSlashed(requestId, operator, operatorSetId, strategies, wadToSlash, description);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the core will emit this event

}
}
Loading
Loading