Skip to content
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
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
48 changes: 48 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,58 @@ 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.

```mermaid
graph TD
Alice --> |call| Proxy["AllocationManager Proxy"]
Proxy -->|delegatecall| Logic["AllocationManager Logic"]
Logic -->|_delegateView| View["AllocationManager View"]
```

### 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 conveniently indicates which calls are intended to be delegated as view functions, but it does not enforce this at the EVM level; rather, it signals intended usage and expected behavior to the user or integrator.
- Both contracts are aligned in storage layout, so all state variables are accessible as intended.

This pattern is especially useful for complex contracts that require a comprehensive set of view functions while maintaining the ability to perform state mutations. It helps keep contracts deployable within EVM bytecode limits, while making clear which functions are for data retrieval.

## 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