Skip to content

Commit d9e0c7a

Browse files
0xClandestinebowenli86
authored andcommitted
feat: add SlashingWithdrawalRouter (#1358)
**Motivation:** We want to hold slashed funds in escrow temporarily to maintain protocol security (prevent malicious actors from draining the contracts). **Modifications:** - Add `SlashingWithdrawalRouter`. **Result:** The `SlashingWithdrawalRouter` contract is added for managing slashed funds in the EigenLayer protocol. It provides a mechanism to handle the burning or redistribution of slashed shares after a delay period, ensuring proper handling of slashed funds while maintaining protocol security. --------- Co-authored-by: Yash Patil <[email protected]> test(redistribution): add unit tests (#1383) **Motivation:** We want to ensure `SlashingWithdrawalRouter` has appropriate unit test coverage. **Modifications:** - Add more unit tests. **Result:** 90% coverage. refactor: remove `v` prefix from `SemVerMixin` (#1385) **Motivation:** Slashing was deployed with using a `v` prefix, thus we're simply going to drop the prefix moving forward. **Modifications:** Prefix removed, and tests updated. **Result:** SemVerMixin no longer requires a `v` prefix. feat: escrow funds in unique clone contracts (#1387) **Motivation:** Current implementation is broken by rebase tokens. **Modifications:** - Rename SWR -> `SlashEscrowFactory`. - Add factory logic that deploys clones unique to their slash ID. **Result:** Funds will now be stored in clone contracts unique to their slash ID. fix: review issues (#1391) **Motivation:** We want to resolve any review issues that arise. **Modifications:** - Use larger of strategy or global delay: @non-fungible-nelson - Fix storage overrides noted from `Deprecated_OwnableUpgradeable` @wadealexc - Use `EnumerableSet` instead of `EnumerableSetUpgradaeable` since it doesn't contain storage - Add missing event in `initialize()`. - Prevent `address(0)` during `createRedistributableOperatorSets` for event sanitation. - Improve check legibility @wadealexc **Result:** Current review concerns have been addressed. fix: storage checker (#1394) **Motivation:** Storage checker didn't have ALM added. Also we needed to fix the deprecated ownable mixing. **Modifications:** Fix mixing to inherit from `ContextUpgradeable`. Add ALM to storage-diff.json. **Result:** Correct storage checks. --------- Co-authored-by: Yash Patil <[email protected]> chore: use internal getters; update `isOperatorRedistributable` (#1401) **Motivation:** We want to use internal getters wherever possible for style. **Modifications:** - Use `getRedistributionRecipient` in `isOperatorRedistributable` - Update `isOperatorRedistributable` to get all allocated/registered sets and then check if slashable and redistributable set for each - More comprehensive unit tests **Result:** Cleaner code + tests passing chore: rename burnable -> burnOrRedistributable; fix storage gap; remove poc code (#1397) **Motivation:** Burn shares naming is confusing, since shares are burnOrRedistributable **Modifications:** - For the new withdrawal path, call it `burnOrRedistributable`, so `burnOrRedistributableSharesIncreased` or `burnOrRedistributableSharesDecreased` - Bring back `burnableSharesDecreased` event for the legacy burn path - Rename `_operatorSetBurnableShares` to `_burnOrRedistributableShares` - Fix the storage gap, since `_burnOrRedistributableShares` is a mapping pointing to an enumerable map, not an enumerable map - Remove POC withdrawal queue code from the DM **Result:** Cleaner Redistribution code chore: remove dm/alm code size optimizations (#1398) **Motivation:** We have several code size optimizations in the DM/ALM. These are not needed anymore with the ownable deprecation. We can add in future upgrade if we want. **Modifications:** Remove all internal `_check` and modifiers. Make `slashOperatorShares` in the DM return to the original non-arrayified method. **Result:** Smaller code diff for redistribution. test: full coverage `SlashEscrowFactory` + `SlashEscrow` (#1403) **Motivation:** We want to ensure we have full coverage unit tests for `SlashEscrowFactory` and `SlashEscrow` in preparation for audits. **Modifications:** - Adds checks for all view methods. **Result:** Brings coverage up to 100% for all branches/fns/etc. feat: redistribution upgrade scripts chore: remove added code fix: epm paused status for sepolia chore: format fix: typo Co-authored-by: bowenli86 <[email protected]>
1 parent 6c0a035 commit d9e0c7a

File tree

64 files changed

+3967
-1398
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+3967
-1398
lines changed

.github/configs/storage-diff.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
22
"contracts": [
3+
{
4+
"name": "AllocationManager",
5+
"address": "0x948a420b8CC1d6BFd0B6087C2E7c344a2CD0bc39"
6+
},
37
{
48
"name": "AVSDirectory",
59
"address": "0x135dda560e946695d6f155dacafc6f1f25c1f5af"

.gitmodules

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
[submodule "lib/ds-test"]
22
path = lib/ds-test
33
url = https://github.com/dapphub/ds-test
4-
[submodule "lib/forge-std"]
5-
path = lib/forge-std
6-
url = https://github.com/foundry-rs/forge-std
74
[submodule "lib/openzeppelin-contracts-v4.9.0"]
85
path = lib/openzeppelin-contracts-v4.9.0
96
url = https://github.com/OpenZeppelin/openzeppelin-contracts
@@ -13,3 +10,6 @@
1310
[submodule "lib/zeus-templates"]
1411
path = lib/zeus-templates
1512
url = https://github.com/Layr-Labs/zeus-templates
13+
[submodule "lib/forge-std"]
14+
path = lib/forge-std
15+
url = https://github.com/foundry-rs/forge-std

script/deploy/devnet/deploy_from_scratch.s.sol

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ import "../../../src/contracts/core/AVSDirectory.sol";
1414
import "../../../src/contracts/core/RewardsCoordinator.sol";
1515
import "../../../src/contracts/core/AllocationManager.sol";
1616
import "../../../src/contracts/permissions/PermissionController.sol";
17-
17+
import "../../../src/contracts/core/SlashEscrowFactory.sol";
1818
import "../../../src/contracts/strategies/StrategyBaseTVLLimits.sol";
1919
import "../../../src/contracts/strategies/StrategyFactory.sol";
2020
import "../../../src/contracts/strategies/StrategyBase.sol";
21+
import "../../../src/contracts/core/SlashEscrow.sol";
2122

2223
import "../../../src/contracts/pods/EigenPod.sol";
2324
import "../../../src/contracts/pods/EigenPodManager.sol";
@@ -63,6 +64,8 @@ contract DeployFromScratch is Script, Test {
6364
AllocationManager public allocationManager;
6465
PermissionController public permissionController;
6566
PermissionController public permissionControllerImplementation;
67+
SlashEscrowFactory public slashEscrowFactory;
68+
SlashEscrowFactory public slashEscrowFactoryImplementation;
6669

6770
EmptyContract public emptyContract;
6871

@@ -214,6 +217,9 @@ contract DeployFromScratch is Script, Test {
214217
permissionController = PermissionController(
215218
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
216219
);
220+
slashEscrowFactory = SlashEscrowFactory(
221+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
222+
);
217223

218224
// if on mainnet, use the ETH2 deposit contract address
219225
if (chainId == 1) ethPOSDeposit = IETHPOSDeposit(0x00000000219ab540356cBB839Cbe05303d7705Fa);
@@ -235,7 +241,7 @@ contract DeployFromScratch is Script, Test {
235241
SEMVER
236242
);
237243

238-
strategyManagerImplementation = new StrategyManager(delegation, eigenLayerPauserReg, SEMVER);
244+
strategyManagerImplementation = new StrategyManager(delegation, slashEscrowFactory, eigenLayerPauserReg, SEMVER);
239245
avsDirectoryImplementation = new AVSDirectory(delegation, eigenLayerPauserReg, SEMVER);
240246
eigenPodManagerImplementation =
241247
new EigenPodManager(ethPOSDeposit, eigenPodBeacon, delegation, eigenLayerPauserReg, SEMVER);
@@ -264,6 +270,8 @@ contract DeployFromScratch is Script, Test {
264270
);
265271
permissionControllerImplementation = new PermissionController(SEMVER);
266272
strategyFactoryImplementation = new StrategyFactory(strategyManager, eigenLayerPauserReg, SEMVER);
273+
slashEscrowFactoryImplementation =
274+
new SlashEscrowFactory(allocationManager, strategyManager, eigenLayerPauserReg, new SlashEscrow(), SEMVER);
267275

268276
// Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them.
269277
{
@@ -537,9 +545,9 @@ contract DeployFromScratch is Script, Test {
537545

538546
function _verifyInitialOwners() internal view {
539547
require(strategyManager.owner() == executorMultisig, "strategyManager: owner not set correctly");
540-
require(delegation.owner() == executorMultisig, "delegation: owner not set correctly");
548+
// require(delegation.owner() == executorMultisig, "delegation: owner not set correctly");
541549
require(eigenPodManager.owner() == executorMultisig, "eigenPodManager: owner not set correctly");
542-
require(allocationManager.owner() == executorMultisig, "allocationManager: owner not set correctly");
550+
// require(allocationManager.owner() == executorMultisig, "allocationManager: owner not set correctly");
543551
require(eigenLayerProxyAdmin.owner() == executorMultisig, "eigenLayerProxyAdmin: owner not set correctly");
544552
require(eigenPodBeacon.owner() == executorMultisig, "eigenPodBeacon: owner not set correctly");
545553
require(strategyBeacon.owner() == executorMultisig, "strategyBeacon: owner not set correctly");

script/deploy/local/deploy_from_scratch.slashing.s.sol

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import "../../../src/contracts/core/AVSDirectory.sol";
1414
import "../../../src/contracts/core/RewardsCoordinator.sol";
1515
import "../../../src/contracts/core/AllocationManager.sol";
1616
import "../../../src/contracts/permissions/PermissionController.sol";
17+
import "../../../src/contracts/core/SlashEscrowFactory.sol";
18+
import "../../../src/contracts/core/SlashEscrow.sol";
1719

1820
import "../../../src/contracts/strategies/StrategyBaseTVLLimits.sol";
1921

@@ -66,6 +68,8 @@ contract DeployFromScratch is Script, Test {
6668
AllocationManager public allocationManager;
6769
PermissionController public permissionControllerImplementation;
6870
PermissionController public permissionController;
71+
SlashEscrowFactory public slashEscrowFactory;
72+
SlashEscrowFactory public slashEscrowFactoryImplementation;
6973

7074
EmptyContract public emptyContract;
7175

@@ -221,6 +225,9 @@ contract DeployFromScratch is Script, Test {
221225
permissionController = PermissionController(
222226
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
223227
);
228+
slashEscrowFactory = SlashEscrowFactory(
229+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
230+
);
224231

225232
// if on mainnet, use the ETH2 deposit contract address
226233
if (chainId == 1) ethPOSDeposit = IETHPOSDeposit(0x00000000219ab540356cBB839Cbe05303d7705Fa);
@@ -241,7 +248,7 @@ contract DeployFromScratch is Script, Test {
241248
MIN_WITHDRAWAL_DELAY,
242249
SEMVER
243250
);
244-
strategyManagerImplementation = new StrategyManager(delegation, eigenLayerPauserReg, SEMVER);
251+
strategyManagerImplementation = new StrategyManager(delegation, slashEscrowFactory, eigenLayerPauserReg, SEMVER);
245252
avsDirectoryImplementation = new AVSDirectory(delegation, eigenLayerPauserReg, SEMVER);
246253
eigenPodManagerImplementation =
247254
new EigenPodManager(ethPOSDeposit, eigenPodBeacon, delegation, eigenLayerPauserReg, SEMVER);
@@ -269,6 +276,8 @@ contract DeployFromScratch is Script, Test {
269276
SEMVER
270277
);
271278
permissionControllerImplementation = new PermissionController(SEMVER);
279+
slashEscrowFactoryImplementation =
280+
new SlashEscrowFactory(allocationManager, strategyManager, eigenLayerPauserReg, new SlashEscrow(), SEMVER);
272281

273282
// Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them.
274283
{
@@ -538,7 +547,7 @@ contract DeployFromScratch is Script, Test {
538547

539548
function _verifyInitialOwners() internal view {
540549
require(strategyManager.owner() == executorMultisig, "strategyManager: owner not set correctly");
541-
require(delegation.owner() == executorMultisig, "delegation: owner not set correctly");
550+
// require(delegation.owner() == executorMultisig, "delegation: owner not set correctly");
542551
require(eigenPodManager.owner() == executorMultisig, "eigenPodManager: owner not set correctly");
543552

544553
require(eigenLayerProxyAdmin.owner() == executorMultisig, "eigenLayerProxyAdmin: owner not set correctly");

script/output/devnet/SLASHING_deploy_from_scratch_deployment_data.json

Lines changed: 0 additions & 52 deletions
This file was deleted.

script/releases/Env.sol

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import "src/contracts/core/RewardsCoordinator.sol";
1515
import "src/contracts/interfaces/IRewardsCoordinator.sol";
1616
import "src/contracts/core/StrategyManager.sol";
1717

18+
/// slashEscrow/
19+
import "src/contracts/core/SlashEscrow.sol";
20+
import "src/contracts/core/SlashEscrowFactory.sol";
21+
1822
/// permissions/
1923
import "src/contracts/permissions/PauserRegistry.sol";
2024
import "src/contracts/permissions/PermissionController.sol";
@@ -76,6 +80,10 @@ library Env {
7680
return _envAddress("operationsMultisig");
7781
}
7882

83+
function communityMultisig() internal view returns (address) {
84+
return _envAddress("communityMultisig");
85+
}
86+
7987
function protocolCouncilMultisig() internal view returns (address) {
8088
return _envAddress("protocolCouncilMultisig");
8189
}
@@ -88,6 +96,10 @@ library Env {
8896
return _envAddress("proxyAdmin");
8997
}
9098

99+
function slashEscrowProxyAdmin() internal view returns (address) {
100+
return _envAddress("slashEscrowProxyAdmin");
101+
}
102+
91103
function ethPOS() internal view returns (IETHPOSDeposit) {
92104
return IETHPOSDeposit(_envAddress("ethPOS"));
93105
}
@@ -148,6 +160,10 @@ library Env {
148160
return _envU256("REWARDS_COORDINATOR_PAUSE_STATUS");
149161
}
150162

163+
function SLASH_ESCROW_DELAY() internal view returns (uint32) {
164+
return _envU32("SLASH_ESCROW_DELAY");
165+
}
166+
151167
/**
152168
* core/
153169
*/
@@ -318,6 +334,27 @@ library Env {
318334
return StrategyFactory(_deployedImpl(type(StrategyFactory).name));
319335
}
320336

337+
/**
338+
* slashEscrow/
339+
*/
340+
function slashEscrow(
341+
DeployedImpl
342+
) internal view returns (SlashEscrow) {
343+
return SlashEscrow(_deployedImpl(type(SlashEscrow).name));
344+
}
345+
346+
function slashEscrowFactory(
347+
DeployedProxy
348+
) internal view returns (SlashEscrowFactory) {
349+
return SlashEscrowFactory(_deployedProxy(type(SlashEscrowFactory).name));
350+
}
351+
352+
function slashEscrowFactory(
353+
DeployedImpl
354+
) internal view returns (SlashEscrowFactory) {
355+
return SlashEscrowFactory(_deployedImpl(type(SlashEscrowFactory).name));
356+
}
357+
321358
/**
322359
* token/
323360
*/

0 commit comments

Comments
 (0)