Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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: 1 addition & 1 deletion .github/workflows/validate-deployment-scripts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de
with:
version: stable
version: v1.3.5

# Run Forge's formatting checker to ensure consistent code style.
- name: "Forge Fmt"
Expand Down
41 changes: 41 additions & 0 deletions docs/core/AllocationManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Libraries and Mixins:

| File | Notes |
| -------- | -------- |
| [`SplitContractMixin.sol`](../../src/contracts/mixins/SplitContractMixin.sol) | contract splitting for codesize optimization |
| [`PermissionControllerMixin.sol`](../../src/contracts/mixins/PermissionControllerMixin.sol) | account delegation |
| [`Deprecated_OwnableUpgradeable`](../../src/contracts/mixins/Deprecated_OwnableUpgradeable.sol) | deprecated ownable logic |
| [`Pausable.sol`](../../src/contracts/permissions/Pausable.sol) | |
Expand All @@ -29,11 +30,51 @@ The `AllocationManager` manages AVS metadata registration, registration and dere

The `AllocationManager's` responsibilities are broken down into the following concepts:

* [Contract Architecture](#contract-architecture)
* [AVS Metadata](#avs-metadata)
* [Operator Sets](#operator-sets)
* [Allocations and Slashing](#allocations-and-slashing)
* [Config](#config)

## Contract Architecture

The `AllocationManager` uses a **split contract pattern** implemented via the `SplitContractMixin` to address EVM contract size limitations while maintaining full backwards compatibility.

### Split Contract Pattern

**Main Contract (`AllocationManager`):**
- Contains all state-mutating functions (actions)
- Inherits from `SplitContractMixin` which provides delegation capabilities
- Delegates all view function calls to the separate view contract
- Maintains the same external interface as a monolithic contract

**View Contract (`AllocationManagerView`):**
- Contains all read-only view functions
- Shares the same storage layout as the main contract using `layout at 151` directive
- Implements the same `IAllocationManagerView` interface

### Rationale

**Codesize Optimization:**
- The EVM has a contract size limit of 24KB (24,576 bytes) for deployed contracts
- Complex contracts like `AllocationManager` with extensive functionality can exceed this limit
- By splitting view functions into a separate contract, the main contract stays under the size limit
- This allows for more comprehensive functionality without compromising deployability

**Backwards Compatibility:**
- The external interface remains identical to a monolithic contract
- All existing integrations continue to work without modification
- View functions are transparently delegated using `_delegateView()`
- No breaking changes to the ABI or function signatures

**Implementation Details:**
- View functions in the main contract use `_delegateView(viewImplementation)` to delegate calls
- The `viewImplementation` address is set during construction and stored as an immutable variable
- The `_delegateView()` function uses assembly to safely cast the non-view `_delegate()` function to a view context
- Storage layout alignment ensures both contracts access the same state variables correctly

This pattern is particularly valuable for complex contracts that need extensive view functionality while maintaining the ability to perform state mutations, ensuring both functionality and deployability on the EVM.

## Parameterization

* `ALLOCATION_CONFIGURATION_DELAY`: The delay in blocks before allocations take effect.
Expand Down
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"forge-std/=lib/forge-std/src/"
]
# Specifies the exact version of Solidity to use, overriding auto-detection.
solc_version = '0.8.27'
solc_version = '0.8.30'
# If enabled, treats Solidity compiler warnings as errors, preventing artifact generation if warnings are present.
deny_warnings = true
# If set to true, changes compilation pipeline to go through the new IR optimizer.
Expand Down
15 changes: 11 additions & 4 deletions script/deploy/devnet/deploy_from_scratch.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "../../../src/contracts/core/DelegationManager.sol";
import "../../../src/contracts/core/AVSDirectory.sol";
import "../../../src/contracts/core/RewardsCoordinator.sol";
import "../../../src/contracts/core/AllocationManager.sol";
import "../../../src/contracts/core/AllocationManagerView.sol";
import "../../../src/contracts/permissions/PermissionController.sol";
import "../../../src/contracts/strategies/StrategyBaseTVLLimits.sol";
import "../../../src/contracts/strategies/StrategyFactory.sol";
Expand Down Expand Up @@ -60,6 +61,7 @@ contract DeployFromScratch is Script, Test {
StrategyBase public baseStrategyImplementation;
AllocationManager public allocationManagerImplementation;
AllocationManager public allocationManager;
AllocationManagerView public allocationManagerView;
PermissionController public permissionController;
PermissionController public permissionControllerImplementation;

Expand Down Expand Up @@ -211,6 +213,9 @@ contract DeployFromScratch is Script, Test {
strategyFactory = StrategyFactory(
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
);
allocationManagerView = AllocationManagerView(
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
);
permissionController = PermissionController(
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
);
Expand All @@ -228,22 +233,23 @@ contract DeployFromScratch is Script, Test {
delegationImplementation = new DelegationManager(
strategyManager,
eigenPodManager,
allocationManager,
IAllocationManager(address(allocationManager)),
eigenLayerPauserReg,
permissionController,
MIN_WITHDRAWAL_DELAY,
SEMVER
);

strategyManagerImplementation = new StrategyManager(allocationManager, delegation, eigenLayerPauserReg, SEMVER);
strategyManagerImplementation =
new StrategyManager(IAllocationManager(address(allocationManager)), delegation, eigenLayerPauserReg, SEMVER);
avsDirectoryImplementation = new AVSDirectory(delegation, eigenLayerPauserReg, SEMVER);
eigenPodManagerImplementation =
new EigenPodManager(ethPOSDeposit, eigenPodBeacon, delegation, eigenLayerPauserReg, SEMVER);
rewardsCoordinatorImplementation = new RewardsCoordinator(
IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams(
delegation,
strategyManager,
allocationManager,
IAllocationManager(address(allocationManager)),
eigenLayerPauserReg,
permissionController,
REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS,
Expand All @@ -255,6 +261,7 @@ contract DeployFromScratch is Script, Test {
)
);
allocationManagerImplementation = new AllocationManager(
allocationManagerView,
delegation,
eigenStrategy,
eigenLayerPauserReg,
Expand Down Expand Up @@ -480,7 +487,7 @@ contract DeployFromScratch is Script, Test {
"rewardsCoordinator: strategyManager address not set correctly"
);
require(
delegationContract.allocationManager() == allocationManager,
delegationContract.allocationManager() == IAllocationManager(address(allocationManager)),
"delegationManager: allocationManager address not set correctly"
);
require(
Expand Down
13 changes: 10 additions & 3 deletions script/deploy/local/deploy_from_scratch.slashing.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import "../../../src/contracts/core/DelegationManager.sol";
import "../../../src/contracts/core/AVSDirectory.sol";
import "../../../src/contracts/core/RewardsCoordinator.sol";
import "../../../src/contracts/core/AllocationManager.sol";
import "../../../src/contracts/core/AllocationManagerView.sol";
import "../../../src/contracts/permissions/PermissionController.sol";

import "../../../src/contracts/strategies/StrategyBaseTVLLimits.sol";
Expand Down Expand Up @@ -65,6 +66,7 @@ contract DeployFromScratch is Script, Test {
StrategyBase public baseStrategyImplementation;
AllocationManager public allocationManagerImplementation;
AllocationManager public allocationManager;
AllocationManagerView public allocationManagerView;
PermissionController public permissionControllerImplementation;
PermissionController public permissionController;

Expand Down Expand Up @@ -219,6 +221,9 @@ contract DeployFromScratch is Script, Test {
allocationManager = AllocationManager(
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
);
allocationManagerView = AllocationManagerView(
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
);
permissionController = PermissionController(
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
);
Expand All @@ -238,21 +243,22 @@ contract DeployFromScratch is Script, Test {
delegationImplementation = new DelegationManager(
strategyManager,
eigenPodManager,
allocationManager,
IAllocationManager(address(allocationManager)),
eigenLayerPauserReg,
permissionController,
MIN_WITHDRAWAL_DELAY,
SEMVER
);
strategyManagerImplementation = new StrategyManager(allocationManager, delegation, eigenLayerPauserReg, SEMVER);
strategyManagerImplementation =
new StrategyManager(IAllocationManager(address(allocationManager)), delegation, eigenLayerPauserReg, SEMVER);
avsDirectoryImplementation = new AVSDirectory(delegation, eigenLayerPauserReg, SEMVER);
eigenPodManagerImplementation =
new EigenPodManager(ethPOSDeposit, eigenPodBeacon, delegation, eigenLayerPauserReg, SEMVER);
rewardsCoordinatorImplementation = new RewardsCoordinator(
IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams(
delegation,
strategyManager,
allocationManager,
IAllocationManager(address(allocationManager)),
eigenLayerPauserReg,
permissionController,
REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS,
Expand All @@ -264,6 +270,7 @@ contract DeployFromScratch is Script, Test {
)
);
allocationManagerImplementation = new AllocationManager(
allocationManagerView,
delegation,
eigenStrategy,
eigenLayerPauserReg,
Expand Down
28 changes: 24 additions & 4 deletions script/releases/Env.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.so

/// core/
import "src/contracts/core/AllocationManager.sol";
import "src/contracts/core/AllocationManagerView.sol";
import "src/contracts/core/AVSDirectory.sol";
import "src/contracts/core/DelegationManager.sol";
import "src/contracts/core/RewardsCoordinator.sol";
import "src/contracts/interfaces/IRewardsCoordinator.sol";
import "src/contracts/core/StrategyManager.sol";
import "src/contracts/core/ReleaseManager.sol";
import "src/contracts/core/ProtocolRegistry.sol";

/// permissions/
import "src/contracts/permissions/PauserRegistry.sol";
Expand Down Expand Up @@ -206,14 +208,20 @@ library Env {
*/
function allocationManager(
DeployedProxy
) internal view returns (AllocationManager) {
return AllocationManager(_deployedProxy(type(AllocationManager).name));
) internal view returns (IAllocationManager) {
return IAllocationManager(_deployedProxy(type(AllocationManager).name));
}

function allocationManager(
DeployedImpl
) internal view returns (AllocationManager) {
return AllocationManager(_deployedImpl(type(AllocationManager).name));
) internal view returns (IAllocationManager) {
return IAllocationManager(_deployedImpl(type(AllocationManager).name));
}

function allocationManagerView(
DeployedImpl
) internal view returns (IAllocationManagerView) {
return IAllocationManagerView(_deployedImpl(type(AllocationManagerView).name));
}

function avsDirectory(
Expand Down Expand Up @@ -276,6 +284,18 @@ library Env {
return ReleaseManager(_deployedImpl(type(ReleaseManager).name));
}

function protocolRegistry(
DeployedProxy
) internal view returns (ProtocolRegistry) {
return ProtocolRegistry(_deployedProxy(type(ProtocolRegistry).name));
}

function protocolRegistry(
DeployedImpl
) internal view returns (ProtocolRegistry) {
return ProtocolRegistry(_deployedImpl(type(ProtocolRegistry).name));
}

/**
* permissions/
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ contract DeploySourceChain is EOADeployer {
deployedTo: address(
new KeyRegistrar({
_permissionController: Env.proxy.permissionController(),
_allocationManager: Env.proxy.allocationManager(),
_allocationManager: IAllocationManager(address(Env.proxy.allocationManager())),
_version: Env.deployVersion()
})
)
Expand All @@ -48,7 +48,7 @@ contract DeploySourceChain is EOADeployer {
name: type(CrossChainRegistry).name,
deployedTo: address(
new CrossChainRegistry({
_allocationManager: Env.proxy.allocationManager(),
_allocationManager: IAllocationManager(address(Env.proxy.allocationManager())),
_keyRegistrar: Env.proxy.keyRegistrar(),
_permissionController: Env.proxy.permissionController(),
_pauserRegistry: Env.impl.pauserRegistry(),
Expand Down
3 changes: 2 additions & 1 deletion script/tasks/complete_withdrawal_from_strategy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ contract CompleteWithdrawFromStrategy is Script, Test {
DepositScalingFactor memory dsf = DepositScalingFactor(dm.depositScalingFactor(msg.sender, strategies[0]));

// Get TM for Operator in strategies
uint64[] memory maxMagnitudes = am.getMaxMagnitudesAtBlock(msg.sender, strategies, startBlock);
uint64[] memory maxMagnitudes =
IAllocationManager(address(am)).getMaxMagnitudesAtBlock(msg.sender, strategies, startBlock);
uint256 slashingFactor = _getSlashingFactor(em, msg.sender, strategies[0], maxMagnitudes[0]);
uint256 sharesToWithdraw = dsf.calcWithdrawable(amount, slashingFactor);

Expand Down
17 changes: 13 additions & 4 deletions script/utils/ExistingDeploymentParser.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "../../src/contracts/core/DelegationManager.sol";
import "../../src/contracts/core/AVSDirectory.sol";
import "../../src/contracts/core/RewardsCoordinator.sol";
import "../../src/contracts/core/AllocationManager.sol";
import "../../src/contracts/core/AllocationManagerView.sol";
import "../../src/contracts/permissions/PermissionController.sol";

import "../../src/contracts/strategies/StrategyFactory.sol";
Expand Down Expand Up @@ -104,8 +105,9 @@ contract ExistingDeploymentParser is Script, Logger {
UpgradeableBeacon public strategyBeacon;

/// @dev AllocationManager
AllocationManager public allocationManager;
AllocationManager public allocationManagerImplementation;
IAllocationManager public allocationManager;
IAllocationManager public allocationManagerImplementation;
IAllocationManagerView public allocationManagerView;

/// @dev AVSDirectory
AVSDirectory public avsDirectory;
Expand Down Expand Up @@ -230,9 +232,16 @@ contract ExistingDeploymentParser is Script, Logger {
);

// AllocationManager
allocationManager = AllocationManager(json.readAddress(".addresses.allocationManager"));
allocationManager = IAllocationManager(json.readAddress(".addresses.allocationManager"));
allocationManagerImplementation =
AllocationManager(json.readAddress(".addresses.allocationManagerImplementation"));
IAllocationManager(json.readAddress(".addresses.allocationManagerImplementation"));

// allocationManagerView = IAllocationManagerView(json.readAddress(".addresses.allocationManagerView"));

// FIXME: hotfix - remove later...
allocationManagerView = new AllocationManagerView(
delegationManager, eigenStrategy, DEALLOCATION_DELAY, ALLOCATION_CONFIGURATION_DELAY
);

// AVSDirectory
avsDirectory = AVSDirectory(json.readAddress(".addresses.avsDirectory"));
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/core/AVSDirectory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import "@openzeppelin-upgrades/contracts/security/ReentrancyGuardUpgradeable.sol

import "../mixins/SignatureUtilsMixin.sol";
import "../permissions/Pausable.sol";
import "./AVSDirectoryStorage.sol";
import "./storage/AVSDirectoryStorage.sol";

contract AVSDirectory is
Initializable,
Expand Down
Loading
Loading