diff --git a/src/contracts/core/AVSDirectory.sol b/src/contracts/core/AVSDirectory.sol index f8a52f59d..4892fcecc 100644 --- a/src/contracts/core/AVSDirectory.sol +++ b/src/contracts/core/AVSDirectory.sol @@ -7,7 +7,6 @@ import "@openzeppelin-upgrades/contracts/security/ReentrancyGuardUpgradeable.sol import "../permissions/Pausable.sol"; import "../libraries/EIP1271SignatureUtils.sol"; -import "../interfaces/IDelegationManager.sol"; import "./AVSDirectoryStorage.sol"; contract AVSDirectory is @@ -20,47 +19,6 @@ contract AVSDirectory is using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.AddressSet; - // Constants - - /// @notice The EIP-712 typehash for the contract's domain - bytes32 public constant DOMAIN_TYPEHASH = - keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); - - /// @notice The EIP-712 typehash for the `Registration` struct used by the contract - bytes32 public constant OPERATOR_AVS_REGISTRATION_TYPEHASH = - keccak256("OperatorAVSRegistration(address operator,address avs,bytes32 salt,uint256 expiry)"); - - /// @notice The EIP-712 typehash for the `OperatorSetRegistration` struct used by the contract - bytes32 public constant OPERATOR_SET_REGISTRATION_TYPEHASH = - keccak256("OperatorSetRegistration(address avs,uint32[] operatorSetIds,bytes32 salt,uint256 expiry)"); - - /// @notice The EIP-712 typehash for the `OperatorSetMembership` struct used by the contract - bytes32 public constant OPERATOR_SET_FORCE_DEREGISTRATION_TYPEHASH = - keccak256("OperatorSetForceDeregistration(address avs,uint32[] operatorSetIds,bytes32 salt,uint256 expiry)"); - - /// @notice The EIP-712 typehash for the `MagnitudeAdjustments` struct used by the contract - bytes32 public constant MAGNITUDE_ADJUSTMENT_TYPEHASH = keccak256( - "MagnitudeAdjustments(address operator,MagnitudeAdjustment(address strategy, OperatorSet(address avs, uint32 operatorSetId)[], uint64[] magnitudeDiffs)[],bytes32 salt,uint256 expiry)" - ); - - /// @dev Index for flag that pauses operator register/deregister to avs when set. - uint8 internal constant PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS = 0; - - /// @dev Index for flag that pauses operator register/deregister to operator sets when set. - uint8 internal constant PAUSED_OPERATOR_SET_REGISTRATION_AND_DEREGISTRATION = 1; - - // Immutables - - /// @notice The DelegationManager contract for EigenLayer - IDelegationManager public immutable delegation; - - /// @notice Delay before deallocations are completable and can be added back into freeMagnitude - /// In this window, deallocations still remain slashable by the operatorSet they were allocated to. - uint32 public immutable DEALLOCATION_DELAY; - - /// @dev Returns the chain ID from the time the contract was deployed. - uint256 internal immutable ORIGINAL_CHAIN_ID; - /** * * INITIALIZING FUNCTIONS @@ -74,10 +32,8 @@ contract AVSDirectory is constructor( IDelegationManager _delegation, uint32 _DEALLOCATION_DELAY - ) { + ) AVSDirectoryStorage(_delegation, _DEALLOCATION_DELAY) { _disableInitializers(); - DEALLOCATION_DELAY = _DEALLOCATION_DELAY; - ORIGINAL_CHAIN_ID = block.chainid; } /** diff --git a/src/contracts/core/AVSDirectoryStorage.sol b/src/contracts/core/AVSDirectoryStorage.sol index f8f211ac7..2fa1137a0 100644 --- a/src/contracts/core/AVSDirectoryStorage.sol +++ b/src/contracts/core/AVSDirectoryStorage.sol @@ -4,11 +4,55 @@ pragma solidity ^0.8.27; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "../interfaces/IAVSDirectory.sol"; +import "../interfaces/IDelegationManager.sol"; abstract contract AVSDirectoryStorage is IAVSDirectory { using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.AddressSet; + // Constants + + /// @notice The EIP-712 typehash for the contract's domain + bytes32 public constant DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); + + /// @notice The EIP-712 typehash for the `Registration` struct used by the contract + bytes32 public constant OPERATOR_AVS_REGISTRATION_TYPEHASH = + keccak256("OperatorAVSRegistration(address operator,address avs,bytes32 salt,uint256 expiry)"); + + /// @notice The EIP-712 typehash for the `OperatorSetRegistration` struct used by the contract + bytes32 public constant OPERATOR_SET_REGISTRATION_TYPEHASH = + keccak256("OperatorSetRegistration(address avs,uint32[] operatorSetIds,bytes32 salt,uint256 expiry)"); + + /// @notice The EIP-712 typehash for the `OperatorSetMembership` struct used by the contract + bytes32 public constant OPERATOR_SET_FORCE_DEREGISTRATION_TYPEHASH = + keccak256("OperatorSetForceDeregistration(address avs,uint32[] operatorSetIds,bytes32 salt,uint256 expiry)"); + + /// @notice The EIP-712 typehash for the `MagnitudeAdjustments` struct used by the contract + bytes32 public constant MAGNITUDE_ADJUSTMENT_TYPEHASH = keccak256( + "MagnitudeAdjustments(address operator,MagnitudeAdjustment(address strategy, OperatorSet(address avs, uint32 operatorSetId)[], uint64[] magnitudeDiffs)[],bytes32 salt,uint256 expiry)" + ); + + /// @dev Index for flag that pauses operator register/deregister to avs when set. + uint8 internal constant PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS = 0; + + /// @dev Index for flag that pauses operator register/deregister to operator sets when set. + uint8 internal constant PAUSED_OPERATOR_SET_REGISTRATION_AND_DEREGISTRATION = 1; + + // Immutables + + /// @notice The DelegationManager contract for EigenLayer + IDelegationManager public immutable delegation; + + /// @notice Delay before deallocations are completable and can be added back into freeMagnitude + /// In this window, deallocations still remain slashable by the operatorSet they were allocated to. + uint32 public immutable DEALLOCATION_DELAY; + + /// @dev Returns the chain ID from the time the contract was deployed. + uint256 internal immutable ORIGINAL_CHAIN_ID; + + // Mutatables + /** * @notice Original EIP-712 Domain separator for this contract. * @dev The domain separator may change in the event of a fork that modifies the ChainID. @@ -40,6 +84,17 @@ abstract contract AVSDirectoryStorage is IAVSDirectory { /// @notice Mapping: operator => avs => operatorSetId => operator registration status mapping(address => mapping(address => mapping(uint32 => OperatorSetRegistrationStatus))) public operatorSetStatus; + // Construction + + constructor( + IDelegationManager _delegation, + uint32 _DEALLOCATION_DELAY + ) { + delegation = _delegation; + DEALLOCATION_DELAY = _DEALLOCATION_DELAY; + ORIGINAL_CHAIN_ID = block.chainid; + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/src/contracts/core/AllocationManager.sol b/src/contracts/core/AllocationManager.sol index bae09568f..9dbe529fd 100644 --- a/src/contracts/core/AllocationManager.sol +++ b/src/contracts/core/AllocationManager.sol @@ -8,8 +8,6 @@ import "@openzeppelin-upgrades/contracts/security/ReentrancyGuardUpgradeable.sol import "../permissions/Pausable.sol"; import "../libraries/EIP1271SignatureUtils.sol"; import "../libraries/SlashingLib.sol"; -import "../interfaces/IAVSDirectory.sol"; -import "../interfaces/IDelegationManager.sol"; import "./AllocationManagerStorage.sol"; contract AllocationManager is @@ -21,47 +19,6 @@ contract AllocationManager is { using Snapshots for Snapshots.History; - // Constants - - /// @notice The EIP-712 typehash for the contract's domain - bytes32 public constant DOMAIN_TYPEHASH = - keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); - - /// @notice The EIP-712 typehash for the `MagnitudeAdjustments` struct used by the contract - bytes32 public constant MAGNITUDE_ADJUSTMENT_TYPEHASH = keccak256( - "MagnitudeAdjustments(address operator,MagnitudeAdjustment(address strategy, OperatorSet(address avs, uint32 operatorSetId)[], uint64[] magnitudeDiffs)[],bytes32 salt,uint256 expiry)" - ); - - /// @dev Index for flag that pauses operator allocations/deallocations when set. - uint8 internal constant PAUSED_STAKE_ALLOCATIONS_AND_DEALLOCATIONS = 0; - - /// @dev Index for flag that pauses operator register/deregister to operator sets when set. - uint8 internal constant PAUSED_OPERATOR_SLASHING = 1; - - /// @dev BIPS factor for slashable bips - uint256 internal constant BIPS_FACTOR = 10_000; - - /// @dev Maximum number of pending updates that can be queued for allocations/deallocations - uint256 internal constant MAX_PENDING_UPDATES = 1; - - // Immutables - - /// @notice The DelegationManager contract for EigenLayer - IDelegationManager public immutable delegation; - - /// @notice The AVSDirectory contract for EigenLayer - IAVSDirectory public immutable avsDirectory; - - /// @notice Delay before deallocations are completable and can be added back into freeMagnitude - /// In this window, deallocations still remain slashable by the operatorSet they were allocated to. - uint32 public immutable DEALLOCATION_DELAY; - - /// @dev Delay before alloaction delay modifications take effect. - uint32 public immutable ALLOCATION_CONFIGURATION_DELAY; // QUESTION: 21 days? - - /// @dev Returns the chain ID from the time the contract was deployed. - uint256 internal immutable ORIGINAL_CHAIN_ID; - /** * * INITIALIZING FUNCTIONS @@ -77,11 +34,19 @@ contract AllocationManager is IAVSDirectory _avsDirectory, uint32 _DEALLOCATION_DELAY, uint32 _ALLOCATION_CONFIGURATION_DELAY - ) { + ) + AllocationManagerStorage( + _delegation, + _avsDirectory, + _DEALLOCATION_DELAY, + _ALLOCATION_CONFIGURATION_DELAY + ) + { _disableInitializers(); delegation = _delegation; avsDirectory = _avsDirectory; DEALLOCATION_DELAY = _DEALLOCATION_DELAY; + ALLOCATION_CONFIGURATION_DELAY = _ALLOCATION_CONFIGURATION_DELAY; ORIGINAL_CHAIN_ID = block.chainid; } diff --git a/src/contracts/core/AllocationManagerStorage.sol b/src/contracts/core/AllocationManagerStorage.sol index 11c9284e7..bb4a21d30 100644 --- a/src/contracts/core/AllocationManagerStorage.sol +++ b/src/contracts/core/AllocationManagerStorage.sol @@ -2,11 +2,56 @@ pragma solidity ^0.8.27; import "../interfaces/IAllocationManager.sol"; +import "../interfaces/IAVSDirectory.sol"; +import "../interfaces/IDelegationManager.sol"; import {Snapshots} from "../libraries/Snapshots.sol"; abstract contract AllocationManagerStorage is IAllocationManager { using Snapshots for Snapshots.History; + // Constants + + /// @notice The EIP-712 typehash for the contract's domain + bytes32 public constant DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); + + /// @notice The EIP-712 typehash for the `MagnitudeAdjustments` struct used by the contract + bytes32 public constant MAGNITUDE_ADJUSTMENT_TYPEHASH = keccak256( + "MagnitudeAdjustments(address operator,MagnitudeAdjustment(address strategy, OperatorSet(address avs, uint32 operatorSetId)[], uint64[] magnitudeDiffs)[],bytes32 salt,uint256 expiry)" + ); + + /// @dev Index for flag that pauses operator allocations/deallocations when set. + uint8 internal constant PAUSED_STAKE_ALLOCATIONS_AND_DEALLOCATIONS = 0; + + /// @dev Index for flag that pauses operator register/deregister to operator sets when set. + uint8 internal constant PAUSED_OPERATOR_SLASHING = 1; + + /// @dev BIPS factor for slashable bips + uint256 internal constant BIPS_FACTOR = 10_000; + + /// @dev Maximum number of pending updates that can be queued for allocations/deallocations + uint256 internal constant MAX_PENDING_UPDATES = 1; + + // Immutables + + /// @notice The DelegationManager contract for EigenLayer + IDelegationManager public immutable delegation; + + /// @notice The AVSDirectory contract for EigenLayer + IAVSDirectory public immutable avsDirectory; + + /// @notice Delay before deallocations are completable and can be added back into freeMagnitude + /// In this window, deallocations still remain slashable by the operatorSet they were allocated to. + uint32 public immutable DEALLOCATION_DELAY; + + /// @dev Delay before alloaction delay modifications take effect. + uint32 public immutable ALLOCATION_CONFIGURATION_DELAY; // QUESTION: 21 days? + + /// @dev Returns the chain ID from the time the contract was deployed. + uint256 internal immutable ORIGINAL_CHAIN_ID; + + // Mutatables + /** * @notice Original EIP-712 Domain separator for this contract. * @dev The domain separator may change in the event of a fork that modifies the ChainID. @@ -37,6 +82,21 @@ abstract contract AllocationManagerStorage is IAllocationManager { /// This determines how long it takes for allocations to take effect in the future. mapping(address => AllocationDelayInfo) internal _allocationDelayInfo; + // Construction + + constructor( + IDelegationManager _delegation, + IAVSDirectory _avsDirectory, + uint32 _DEALLOCATION_DELAY, + uint32 _ALLOCATION_CONFIGURATION_DELAY + ) { + delegation = _delegation; + avsDirectory = _avsDirectory; + DEALLOCATION_DELAY = _DEALLOCATION_DELAY; + ALLOCATION_CONFIGURATION_DELAY = _ALLOCATION_CONFIGURATION_DELAY; + ORIGINAL_CHAIN_ID = block.chainid; + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/src/contracts/core/DelegationManager.sol b/src/contracts/core/DelegationManager.sol index 405bc7122..37c5aee14 100644 --- a/src/contracts/core/DelegationManager.sol +++ b/src/contracts/core/DelegationManager.sol @@ -7,10 +7,6 @@ import "@openzeppelin-upgrades/contracts/security/ReentrancyGuardUpgradeable.sol import "../permissions/Pausable.sol"; import "../libraries/EIP1271SignatureUtils.sol"; import "../libraries/SlashingLib.sol"; -import "../interfaces/IStrategyManager.sol"; -import "../interfaces/IAVSDirectory.sol"; -import "../interfaces/IEigenPodManager.sol"; -import "../interfaces/IAllocationManager.sol"; import "./DelegationManagerStorage.sol"; /** @@ -32,62 +28,6 @@ contract DelegationManager is { using SlashingLib for *; - // Constants - - /// @notice The EIP-712 typehash for the contract's domain - bytes32 public constant DOMAIN_TYPEHASH = - keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); - - /// @notice The EIP-712 typehash for the `StakerDelegation` struct used by the contract - bytes32 public constant STAKER_DELEGATION_TYPEHASH = - keccak256("StakerDelegation(address staker,address operator,uint256 nonce,uint256 expiry)"); - - /// @notice The EIP-712 typehash for the `DelegationApproval` struct used by the contract - bytes32 public constant DELEGATION_APPROVAL_TYPEHASH = keccak256( - "DelegationApproval(address delegationApprover,address staker,address operator,bytes32 salt,uint256 expiry)" - ); - - /// @dev Index for flag that pauses new delegations when set - uint8 internal constant PAUSED_NEW_DELEGATION = 0; - - /// @dev Index for flag that pauses queuing new withdrawals when set. - uint8 internal constant PAUSED_ENTER_WITHDRAWAL_QUEUE = 1; - - /// @dev Index for flag that pauses completing existing withdrawals when set. - uint8 internal constant PAUSED_EXIT_WITHDRAWAL_QUEUE = 2; - - /// @notice The minimum number of blocks to complete a withdrawal of a strategy. 50400 * 12 seconds = 1 week - uint256 public constant LEGACY_MIN_WITHDRAWAL_DELAY_BLOCKS = 50_400; - - /// @notice Wed Jan 01 2025 17:00:00 GMT+0000, timestamp used to check whether a pending withdrawal - /// should be processed as legacy M2 or with slashing considered. - uint32 public constant LEGACY_WITHDRAWALS_TIMESTAMP = 1_735_750_800; - - /// @notice Canonical, virtual beacon chain ETH strategy - IStrategy public constant beaconChainETHStrategy = IStrategy(0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0); - - // Immutables - - /// @notice The AVSDirectory contract for EigenLayer - IAVSDirectory public immutable avsDirectory; - - // TODO: Switch these to ShareManagers, but this breaks a lot of tests - - /// @notice The StrategyManager contract for EigenLayer - IStrategyManager public immutable strategyManager; - - /// @notice The EigenPodManager contract for EigenLayer - IEigenPodManager public immutable eigenPodManager; - - /// @notice The AllocationManager contract for EigenLayer - IAllocationManager public immutable allocationManager; - - /// @notice Minimum withdrawal delay in seconds until all queued withdrawals can be completed. - uint32 public immutable MIN_WITHDRAWAL_DELAY; - - /// @dev Chain ID at the time of contract deployment - uint256 internal immutable ORIGINAL_CHAIN_ID; - // @notice Simple permission for functions that are only callable by the StrategyManager contract OR by the EigenPodManagerContract modifier onlyStrategyManagerOrEigenPodManager() { require( @@ -112,14 +52,16 @@ contract DelegationManager is IEigenPodManager _eigenPodManager, IAllocationManager _allocationManager, uint32 _MIN_WITHDRAWAL_DELAY - ) { + ) + DelegationManagerStorage( + _avsDirectory, + _strategyManager, + _eigenPodManager, + _allocationManager, + _MIN_WITHDRAWAL_DELAY + ) + { _disableInitializers(); - avsDirectory = _avsDirectory; - strategyManager = _strategyManager; - eigenPodManager = _eigenPodManager; - allocationManager = _allocationManager; - MIN_WITHDRAWAL_DELAY = _MIN_WITHDRAWAL_DELAY; - ORIGINAL_CHAIN_ID = block.chainid; } /** diff --git a/src/contracts/core/DelegationManagerStorage.sol b/src/contracts/core/DelegationManagerStorage.sol index bcff8327f..321026710 100644 --- a/src/contracts/core/DelegationManagerStorage.sol +++ b/src/contracts/core/DelegationManagerStorage.sol @@ -3,6 +3,9 @@ pragma solidity ^0.8.27; import "../libraries/SlashingLib.sol"; import "../interfaces/IDelegationManager.sol"; +import "../interfaces/IAVSDirectory.sol"; +import "../interfaces/IEigenPodManager.sol"; +import "../interfaces/IAllocationManager.sol"; /** * @title Storage variables for the `DelegationManager` contract. @@ -11,6 +14,64 @@ import "../interfaces/IDelegationManager.sol"; * @notice This storage contract is separate from the logic to simplify the upgrade process. */ abstract contract DelegationManagerStorage is IDelegationManager { + // Constants + + /// @notice The EIP-712 typehash for the contract's domain + bytes32 public constant DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); + + /// @notice The EIP-712 typehash for the `StakerDelegation` struct used by the contract + bytes32 public constant STAKER_DELEGATION_TYPEHASH = + keccak256("StakerDelegation(address staker,address operator,uint256 nonce,uint256 expiry)"); + + /// @notice The EIP-712 typehash for the `DelegationApproval` struct used by the contract + bytes32 public constant DELEGATION_APPROVAL_TYPEHASH = keccak256( + "DelegationApproval(address delegationApprover,address staker,address operator,bytes32 salt,uint256 expiry)" + ); + + /// @dev Index for flag that pauses new delegations when set + uint8 internal constant PAUSED_NEW_DELEGATION = 0; + + /// @dev Index for flag that pauses queuing new withdrawals when set. + uint8 internal constant PAUSED_ENTER_WITHDRAWAL_QUEUE = 1; + + /// @dev Index for flag that pauses completing existing withdrawals when set. + uint8 internal constant PAUSED_EXIT_WITHDRAWAL_QUEUE = 2; + + /// @notice The minimum number of blocks to complete a withdrawal of a strategy. 50400 * 12 seconds = 1 week + uint256 public constant LEGACY_MIN_WITHDRAWAL_DELAY_BLOCKS = 50_400; + + /// @notice Wed Jan 01 2025 17:00:00 GMT+0000, timestamp used to check whether a pending withdrawal + /// should be processed as legacy M2 or with slashing considered. + uint32 public constant LEGACY_WITHDRAWALS_TIMESTAMP = 1_735_750_800; + + /// @notice Canonical, virtual beacon chain ETH strategy + IStrategy public constant beaconChainETHStrategy = IStrategy(0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0); + + // Immutables + + /// @notice The AVSDirectory contract for EigenLayer + IAVSDirectory public immutable avsDirectory; + + // TODO: Switch these to ShareManagers, but this breaks a lot of tests + + /// @notice The StrategyManager contract for EigenLayer + IStrategyManager public immutable strategyManager; + + /// @notice The EigenPodManager contract for EigenLayer + IEigenPodManager public immutable eigenPodManager; + + /// @notice The AllocationManager contract for EigenLayer + IAllocationManager public immutable allocationManager; + + /// @notice Minimum withdrawal delay in seconds until all queued withdrawals can be completed. + uint32 public immutable MIN_WITHDRAWAL_DELAY; + + /// @dev Chain ID at the time of contract deployment + uint256 internal immutable ORIGINAL_CHAIN_ID; + + // Mutatables + /** * @notice Original EIP-712 Domain separator for this contract. * @dev The domain separator may change in the event of a fork that modifies the ChainID. @@ -81,6 +142,23 @@ abstract contract DelegationManagerStorage is IDelegationManager { /// This is updated upon each deposit based on the staker's currently delegated operator's totalMagnitude. mapping(address => mapping(IStrategy => uint256)) public depositScalingFactors; + // Construction + + constructor( + IAVSDirectory _avsDirectory, + IStrategyManager _strategyManager, + IEigenPodManager _eigenPodManager, + IAllocationManager _allocationManager, + uint32 _MIN_WITHDRAWAL_DELAY + ) { + avsDirectory = _avsDirectory; + strategyManager = _strategyManager; + eigenPodManager = _eigenPodManager; + allocationManager = _allocationManager; + MIN_WITHDRAWAL_DELAY = _MIN_WITHDRAWAL_DELAY; + ORIGINAL_CHAIN_ID = block.chainid; + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/src/contracts/core/RewardsCoordinator.sol b/src/contracts/core/RewardsCoordinator.sol index 6f518b03f..f0fdb7354 100644 --- a/src/contracts/core/RewardsCoordinator.sol +++ b/src/contracts/core/RewardsCoordinator.sol @@ -7,7 +7,6 @@ import "@openzeppelin-upgrades/contracts/security/ReentrancyGuardUpgradeable.sol import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../libraries/Merkle.sol"; import "../interfaces/IStrategyManager.sol"; -import "../interfaces/IDelegationManager.sol"; import "../permissions/Pausable.sol"; import "./RewardsCoordinatorStorage.sol"; @@ -29,59 +28,6 @@ contract RewardsCoordinator is { using SafeERC20 for IERC20; - // Constants - - /// @notice The EIP-712 typehash for the contract's domain - bytes32 internal constant DOMAIN_TYPEHASH = - keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); - - /// @notice The maximum rewards token amount for a single rewards submission, constrained by off-chain calculation - uint256 internal constant MAX_REWARDS_AMOUNT = 1e38 - 1; - - /// @dev Index for flag that pauses calling createAVSRewardsSubmission - uint8 internal constant PAUSED_AVS_REWARDS_SUBMISSION = 0; - /// @dev Index for flag that pauses calling createRewardsForAllSubmission - uint8 internal constant PAUSED_REWARDS_FOR_ALL_SUBMISSION = 1; - /// @dev Index for flag that pauses calling processClaim - uint8 internal constant PAUSED_PROCESS_CLAIM = 2; - /// @dev Index for flag that pauses submitRoots and disableRoot - uint8 internal constant PAUSED_SUBMIT_DISABLE_ROOTS = 3; - /// @dev Index for flag that pauses calling rewardAllStakersAndOperators - uint8 internal constant PAUSED_REWARD_ALL_STAKERS_AND_OPERATORS = 4; - - /// @dev Salt for the earner leaf, meant to distinguish from tokenLeaf since they have the same sized data - uint8 internal constant EARNER_LEAF_SALT = 0; - /// @dev Salt for the token leaf, meant to distinguish from earnerLeaf since they have the same sized data - uint8 internal constant TOKEN_LEAF_SALT = 1; - - /// @notice Canonical, virtual beacon chain ETH strategy - IStrategy public constant beaconChainETHStrategy = IStrategy(0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0); - - // Immtuables - - /// @notice The DelegationManager contract for EigenLayer - IDelegationManager public immutable delegationManager; - - /// @notice The StrategyManager contract for EigenLayer - IStrategyManager public immutable strategyManager; - - /// @notice The interval in seconds at which the calculation for rewards distribution is done. - /// @dev RewardsSubmission durations must be multiples of this interval. This is going to be configured to 1 week - uint32 public immutable CALCULATION_INTERVAL_SECONDS; - /// @notice The maximum amount of time (seconds) that a rewards submission can span over - uint32 public immutable MAX_REWARDS_DURATION; - /// @notice max amount of time (seconds) that a rewards submission can start in the past - uint32 public immutable MAX_RETROACTIVE_LENGTH; - /// @notice max amount of time (seconds) that a rewards submission can start in the future - uint32 public immutable MAX_FUTURE_LENGTH; - /// @notice absolute min timestamp (seconds) that a rewards submission can start at - uint32 public immutable GENESIS_REWARDS_TIMESTAMP; - /// @notice The cadence at which a snapshot is taken offchain for calculating rewards distributions - uint32 internal constant SNAPSHOT_CADENCE = 1 days; - - /// @dev Chain ID at the time of contract deployment - uint256 internal immutable ORIGINAL_CHAIN_ID; - modifier onlyRewardsUpdater() { require(msg.sender == rewardsUpdater, UnauthorizedCaller()); _; @@ -101,24 +47,18 @@ contract RewardsCoordinator is uint32 _MAX_RETROACTIVE_LENGTH, uint32 _MAX_FUTURE_LENGTH, uint32 _GENESIS_REWARDS_TIMESTAMP - ) { - require( - _GENESIS_REWARDS_TIMESTAMP % _CALCULATION_INTERVAL_SECONDS == 0, - "RewardsCoordinator: GENESIS_REWARDS_TIMESTAMP must be a multiple of CALCULATION_INTERVAL_SECONDS" - ); - require( - _CALCULATION_INTERVAL_SECONDS % SNAPSHOT_CADENCE == 0, - "RewardsCoordinator: CALCULATION_INTERVAL_SECONDS must be a multiple of SNAPSHOT_CADENCE" - ); + ) + RewardsCoordinatorStorage( + _delegationManager, + _strategyManager, + _CALCULATION_INTERVAL_SECONDS, + _MAX_REWARDS_DURATION, + _MAX_RETROACTIVE_LENGTH, + _MAX_FUTURE_LENGTH, + _GENESIS_REWARDS_TIMESTAMP + ) + { _disableInitializers(); - delegationManager = _delegationManager; - strategyManager = _strategyManager; - CALCULATION_INTERVAL_SECONDS = _CALCULATION_INTERVAL_SECONDS; - MAX_REWARDS_DURATION = _MAX_REWARDS_DURATION; - MAX_RETROACTIVE_LENGTH = _MAX_RETROACTIVE_LENGTH; - MAX_FUTURE_LENGTH = _MAX_FUTURE_LENGTH; - GENESIS_REWARDS_TIMESTAMP = _GENESIS_REWARDS_TIMESTAMP; - ORIGINAL_CHAIN_ID = block.chainid; } /** diff --git a/src/contracts/core/RewardsCoordinatorStorage.sol b/src/contracts/core/RewardsCoordinatorStorage.sol index 6a1ac508e..53bd6d0c5 100644 --- a/src/contracts/core/RewardsCoordinatorStorage.sol +++ b/src/contracts/core/RewardsCoordinatorStorage.sol @@ -2,6 +2,8 @@ pragma solidity ^0.8.27; import "../interfaces/IRewardsCoordinator.sol"; +import "../interfaces/IDelegationManager.sol"; +import "../interfaces/IStrategyManager.sol"; /** * @title Storage variables for the `RewardsCoordinator` contract. @@ -10,6 +12,62 @@ import "../interfaces/IRewardsCoordinator.sol"; * @notice This storage contract is separate from the logic to simplify the upgrade process. */ abstract contract RewardsCoordinatorStorage is IRewardsCoordinator { + + // Constants + + /// @notice The EIP-712 typehash for the contract's domain + bytes32 internal constant DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); + + /// @notice The maximum rewards token amount for a single rewards submission, constrained by off-chain calculation + uint256 internal constant MAX_REWARDS_AMOUNT = 1e38 - 1; + + /// @dev Index for flag that pauses calling createAVSRewardsSubmission + uint8 internal constant PAUSED_AVS_REWARDS_SUBMISSION = 0; + /// @dev Index for flag that pauses calling createRewardsForAllSubmission + uint8 internal constant PAUSED_REWARDS_FOR_ALL_SUBMISSION = 1; + /// @dev Index for flag that pauses calling processClaim + uint8 internal constant PAUSED_PROCESS_CLAIM = 2; + /// @dev Index for flag that pauses submitRoots and disableRoot + uint8 internal constant PAUSED_SUBMIT_DISABLE_ROOTS = 3; + /// @dev Index for flag that pauses calling rewardAllStakersAndOperators + uint8 internal constant PAUSED_REWARD_ALL_STAKERS_AND_OPERATORS = 4; + + /// @dev Salt for the earner leaf, meant to distinguish from tokenLeaf since they have the same sized data + uint8 internal constant EARNER_LEAF_SALT = 0; + /// @dev Salt for the token leaf, meant to distinguish from earnerLeaf since they have the same sized data + uint8 internal constant TOKEN_LEAF_SALT = 1; + + /// @notice Canonical, virtual beacon chain ETH strategy + IStrategy public constant beaconChainETHStrategy = IStrategy(0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0); + + // Immtuables + + /// @notice The DelegationManager contract for EigenLayer + IDelegationManager public immutable delegationManager; + + /// @notice The StrategyManager contract for EigenLayer + IStrategyManager public immutable strategyManager; + + /// @notice The interval in seconds at which the calculation for rewards distribution is done. + /// @dev RewardsSubmission durations must be multiples of this interval. This is going to be configured to 1 week + uint32 public immutable CALCULATION_INTERVAL_SECONDS; + /// @notice The maximum amount of time (seconds) that a rewards submission can span over + uint32 public immutable MAX_REWARDS_DURATION; + /// @notice max amount of time (seconds) that a rewards submission can start in the past + uint32 public immutable MAX_RETROACTIVE_LENGTH; + /// @notice max amount of time (seconds) that a rewards submission can start in the future + uint32 public immutable MAX_FUTURE_LENGTH; + /// @notice absolute min timestamp (seconds) that a rewards submission can start at + uint32 public immutable GENESIS_REWARDS_TIMESTAMP; + /// @notice The cadence at which a snapshot is taken offchain for calculating rewards distributions + uint32 internal constant SNAPSHOT_CADENCE = 1 days; + + /// @dev Chain ID at the time of contract deployment + uint256 internal immutable ORIGINAL_CHAIN_ID; + + // Mutatables + /** * @notice Original EIP-712 Domain separator for this contract. * @dev The domain separator may change in the event of a fork that modifies the ChainID. @@ -55,6 +113,36 @@ abstract contract RewardsCoordinatorStorage is IRewardsCoordinator { /// if rewards submission hash for all stakers and operators has been submitted mapping(address => mapping(bytes32 => bool)) public isRewardsSubmissionForAllEarnersHash; + // Construction + + constructor( + IDelegationManager _delegationManager, + IStrategyManager _strategyManager, + uint32 _CALCULATION_INTERVAL_SECONDS, + uint32 _MAX_REWARDS_DURATION, + uint32 _MAX_RETROACTIVE_LENGTH, + uint32 _MAX_FUTURE_LENGTH, + uint32 _GENESIS_REWARDS_TIMESTAMP + ) { + // TODO: Custom errors or assert (no error message) + require( + _GENESIS_REWARDS_TIMESTAMP % _CALCULATION_INTERVAL_SECONDS == 0, + "RewardsCoordinator: GENESIS_REWARDS_TIMESTAMP must be a multiple of CALCULATION_INTERVAL_SECONDS" + ); + require( + _CALCULATION_INTERVAL_SECONDS % SNAPSHOT_CADENCE == 0, + "RewardsCoordinator: CALCULATION_INTERVAL_SECONDS must be a multiple of SNAPSHOT_CADENCE" + ); + delegationManager = _delegationManager; + strategyManager = _strategyManager; + CALCULATION_INTERVAL_SECONDS = _CALCULATION_INTERVAL_SECONDS; + MAX_REWARDS_DURATION = _MAX_REWARDS_DURATION; + MAX_RETROACTIVE_LENGTH = _MAX_RETROACTIVE_LENGTH; + MAX_FUTURE_LENGTH = _MAX_FUTURE_LENGTH; + GENESIS_REWARDS_TIMESTAMP = _GENESIS_REWARDS_TIMESTAMP; + ORIGINAL_CHAIN_ID = block.chainid; + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/src/contracts/core/StrategyManager.sol b/src/contracts/core/StrategyManager.sol index d615e5668..22533c8d7 100644 --- a/src/contracts/core/StrategyManager.sol +++ b/src/contracts/core/StrategyManager.sol @@ -29,31 +29,6 @@ contract StrategyManager is using SlashingLib for *; using SafeERC20 for IERC20; - // Constants - - /// @notice The EIP-712 typehash for the contract's domain - bytes32 public constant DOMAIN_TYPEHASH = - keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); - /// @notice The EIP-712 typehash for the deposit struct used by the contract - bytes32 public constant DEPOSIT_TYPEHASH = - keccak256("Deposit(address staker,address strategy,address token,uint256 amount,uint256 nonce,uint256 expiry)"); - - // maximum length of dynamic arrays in `stakerStrategyList` mapping, for sanity's sake - uint8 internal constant MAX_STAKER_STRATEGY_LIST_LENGTH = 32; - - // index for flag that pauses deposits when set - uint8 internal constant PAUSED_DEPOSITS = 0; - - // Immutables - - IDelegationManager public immutable delegation; - - IEigenPodManager public immutable eigenPodManager; - - IAVSDirectory public immutable avsDirectory; - - uint256 internal immutable ORIGINAL_CHAIN_ID; - modifier onlyStrategyWhitelister() { require(msg.sender == strategyWhitelister, OnlyStrategyWhitelister()); _; @@ -79,12 +54,8 @@ contract StrategyManager is IDelegationManager _delegation, IEigenPodManager _eigenPodManager, IAVSDirectory _avsDirectory - ) { + ) StrategyManagerStorage(_delegation, _eigenPodManager, _avsDirectory) { _disableInitializers(); - delegation = _delegation; - eigenPodManager = _eigenPodManager; - avsDirectory = _avsDirectory; - ORIGINAL_CHAIN_ID = block.chainid; } // EXTERNAL FUNCTIONS diff --git a/src/contracts/core/StrategyManagerStorage.sol b/src/contracts/core/StrategyManagerStorage.sol index 7dea28669..3b1bd9572 100644 --- a/src/contracts/core/StrategyManagerStorage.sol +++ b/src/contracts/core/StrategyManagerStorage.sol @@ -14,6 +14,33 @@ import "../interfaces/IAVSDirectory.sol"; * @notice This storage contract is separate from the logic to simplify the upgrade process. */ abstract contract StrategyManagerStorage is IStrategyManager { + // Constants + + /// @notice The EIP-712 typehash for the contract's domain + bytes32 public constant DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); + /// @notice The EIP-712 typehash for the deposit struct used by the contract + bytes32 public constant DEPOSIT_TYPEHASH = + keccak256("Deposit(address staker,address strategy,address token,uint256 amount,uint256 nonce,uint256 expiry)"); + + // maximum length of dynamic arrays in `stakerStrategyList` mapping, for sanity's sake + uint8 internal constant MAX_STAKER_STRATEGY_LIST_LENGTH = 32; + + // index for flag that pauses deposits when set + uint8 internal constant PAUSED_DEPOSITS = 0; + + // Immutables + + IDelegationManager public immutable delegation; + + IEigenPodManager public immutable eigenPodManager; + + IAVSDirectory public immutable avsDirectory; + + uint256 internal immutable ORIGINAL_CHAIN_ID; + + // Mutatables + /** * @notice Original EIP-712 Domain separator for this contract. * @dev The domain separator may change in the event of a fork that modifies the ChainID. @@ -65,6 +92,23 @@ abstract contract StrategyManagerStorage is IStrategyManager { */ mapping(IStrategy => bool) private __deprecated_thirdPartyTransfersForbidden; + // Construction + + /** + * @param _delegation The delegation contract of EigenLayer. + * @param _eigenPodManager The contract that keeps track of EigenPod stakes for restaking beacon chain ether. + */ + constructor( + IDelegationManager _delegation, + IEigenPodManager _eigenPodManager, + IAVSDirectory _avsDirectory + ) { + delegation = _delegation; + eigenPodManager = _eigenPodManager; + avsDirectory = _avsDirectory; + ORIGINAL_CHAIN_ID = block.chainid; + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain.