Skip to content

Multiple varied scripts for operational tasks#378

Open
pankajjagtapp wants to merge 9 commits intomasterfrom
pankaj/script/withdrawal-script
Open

Multiple varied scripts for operational tasks#378
pankajjagtapp wants to merge 9 commits intomasterfrom
pankaj/script/withdrawal-script

Conversation

@pankajjagtapp
Copy link
Copy Markdown
Contributor

@pankajjagtapp pankajjagtapp commented Apr 21, 2026

Note

Medium Risk
While these are primarily off-chain forge scripts, they generate and simulate admin/timelock transactions that can materially change mainnet parameters (rate limiter buckets, redemption capacity/fees, whitelist and restaker actions). The update to MIN_DELAY_OPERATING_TIMELOCK (8h→2d) also changes scheduling assumptions for any scripts depending on it.

Overview
Adds several new forge operation scripts that generate batched Gnosis Safe JSON and fork simulations for mainnet ops: priority-queue admin/tag updates and whitelist/fee adjustments (OperationsBatch, WhitelistUsers), rate-limiter capacity/refill changes for consolidations/exits/unrestaking (RaiseRateLimits, ReduceRateLimits), and multiple stETH/EigenLayer restaker workflows (complete+queue stETH withdrawals, claim Lido withdrawals with Safe JSON output, and a 2-step stETH redelegation).

Also adds timelock-driven scripts to temporarily raise EtherFiRedemptionManager stETH redemption capacity/fees (with pre-scheduled revert and fork redemption tests), includes an example Safe JSON for complete-and-queue-steth-withdrawal, broadens foundry.toml FS permissions to all of script/operations, and changes MIN_DELAY_OPERATING_TIMELOCK in Utils from 8 hours to 2 days.

Reviewed by Cursor Bugbot for commit d0633cd. Bugbot is set up for automated code reviews on this repo. Configure here.

@pankajjagtapp pankajjagtapp self-assigned this Apr 21, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 21, 2026

📊 Forge Coverage Report

| File                                       | % Lines            | % Statements       | % Branches       | % Funcs          |
| src/AssetRecovery.sol                      | 100.00% (16/16)    | 96.77% (30/31)     | 85.71% (6/7)     | 100.00% (3/3)    |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/AuctionManager.sol                     | 74.40% (93/125)    | 75.00% (81/108)    | 61.11% (33/54)   | 71.43% (20/28)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/BNFT.sol                               | 53.85% (14/26)     | 56.25% (9/16)      | 20.00% (2/10)    | 45.45% (5/11)    |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/BucketRateLimiter.sol                  | 100.00% (50/50)    | 100.00% (48/48)    | 100.00% (10/10)  | 100.00% (16/16)  |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/CumulativeMerkleRewardsDistributor.sol | 90.41% (66/73)     | 83.33% (70/84)     | 41.18% (7/17)    | 92.86% (13/14)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/DepositAdapter.sol                     | 0.00% (0/57)       | 0.00% (0/65)       | 0.00% (0/11)     | 0.00% (0/9)      |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EETH.sol                               | 97.41% (113/116)   | 97.27% (107/110)   | 90.91% (30/33)   | 96.77% (30/31)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EarlyAdopterPool.sol                   | 0.00% (0/92)       | 0.00% (0/81)       | 0.00% (0/34)     | 0.00% (0/15)     |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiAdmin.sol                       | 95.10% (136/143)   | 93.06% (161/173)   | 76.79% (43/56)   | 95.24% (20/21)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiNode.sol                        | 85.29% (58/68)     | 75.64% (59/78)     | 22.22% (2/9)     | 100.00% (16/16)  |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiNodesManager.sol                | 97.80% (178/182)   | 96.24% (205/213)   | 88.89% (32/36)   | 97.78% (44/45)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiOracle.sol                      | 97.92% (141/144)   | 99.24% (131/132)   | 90.32% (56/62)   | 96.77% (30/31)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiRateLimiter.sol                 | 100.00% (55/55)    | 100.00% (61/61)    | 100.00% (14/14)  | 100.00% (17/17)  |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiRedemptionManager.sol           | 45.75% (70/153)    | 45.56% (77/169)    | 24.56% (14/57)   | 54.55% (18/33)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiRestaker.sol                    | 83.33% (130/156)   | 86.77% (164/189)   | 35.00% (7/20)    | 64.71% (22/34)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiRewardsRouter.sol               | 100.00% (28/28)    | 100.00% (27/27)    | 83.33% (5/6)     | 100.00% (8/8)    |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/LiquidityPool.sol                      | 95.48% (211/221)   | 91.39% (276/302)   | 76.12% (51/67)   | 95.45% (42/44)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/Liquifier.sol                          | 84.52% (131/155)   | 77.11% (128/166)   | 52.50% (21/40)   | 75.00% (30/40)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/MembershipManager.sol                  | 0.00% (0/348)      | 0.00% (0/389)      | 0.00% (0/31)     | 0.00% (0/69)     |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/MembershipNFT.sol                      | 22.73% (40/176)    | 16.42% (33/201)    | 20.69% (6/29)    | 31.71% (13/41)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/NodeOperatorManager.sol                | 89.23% (58/65)     | 92.00% (46/50)     | 80.00% (16/20)   | 80.00% (16/20)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/PriorityWithdrawalQueue.sol            | 92.83% (207/223)   | 83.33% (250/300)   | 50.85% (30/59)   | 95.24% (40/42)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/RestakingRewardsRouter.sol             | 100.00% (33/33)    | 100.00% (34/34)    | 100.00% (7/7)    | 100.00% (7/7)    |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/RoleRegistry.sol                       | 100.00% (24/24)    | 100.00% (18/18)    | 100.00% (2/2)    | 100.00% (11/11)  |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/StakingManager.sol                     | 93.81% (91/97)     | 87.02% (114/131)   | 50.00% (12/24)   | 87.50% (14/16)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/TNFT.sol                               | 58.33% (14/24)     | 60.00% (9/15)      | 25.00% (2/8)     | 50.00% (5/10)    |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/TVLOracle.sol                          | 100.00% (13/13)    | 100.00% (9/9)      | 75.00% (6/8)     | 100.00% (4/4)    |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/WeETH.sol                              | 92.00% (46/50)     | 89.36% (42/47)     | 86.67% (13/15)   | 85.71% (12/14)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/WithdrawRequestNFT.sol                 | 100.00% (139/139)  | 99.31% (143/144)   | 79.37% (50/63)   | 100.00% (29/29)  |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| Total                                      | 70.61% (2155/3052) | 68.77% (2332/3391) | 58.96% (477/809) | 71.43% (485/679) |

---
Ran 5 tests for test/AddressProvider.t.sol:AddressProviderTest
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 37.95ms (7.51ms CPU time)
Ran 23 tests for test/AuctionManager.t.sol:AuctionManagerTest
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 60.15ms (35.48ms CPU time)
Ran 2 tests for test/BNFT.t.sol:BNFTTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 25.35ms (2.71ms CPU time)
Ran 58 tests for test/BucketRaterLimiter.t.sol:BucketRateLimiterTest
Suite result: ok. 58 passed; 0 failed; 0 skipped; finished in 30.37ms (28.72ms CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferBtc.t.sol:LiquidReferBtcTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 4.01s (3.47s CPU time)
Ran 2 tests for test/fork-tests/pectra-fork-tests/Consolidation-through-EOA.sol:ConsolidationThroughEOATest
Suite result: FAILED. 1 passed; 1 failed; 0 skipped; finished in 4.37s (2.72s CPU time)
Ran 2 tests for test/ContractCodeChecker.t.sol:ContractCodeCheckerTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 282.25ms (156.19ms CPU time)
Ran 9 tests for test/CumulativeMerkleRewardsDistributor.t.sol:CumulativeMerkleRewardsDistributorTest
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 38.71ms (15.16ms CPU time)
Ran 3 tests for test/behaviour-tests/pectra-fork-tests/Request-consolidation.t.sol:RequestConsolidationTest
Suite result: FAILED. 0 passed; 3 failed; 0 skipped; finished in 5.04s (2.88s CPU time)
Ran 27 tests for test/RestakingRewardsRouter.t.sol:RestakingRewardsRouterTest
Suite result: ok. 27 passed; 0 failed; 0 skipped; finished in 14.85ms (11.87ms CPU time)
Ran 9 tests for test/RoleRegistry.t.sol:RoleRegistryTest
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 3.05ms (2.18ms CPU time)
Ran 21 tests for test/StakingManager.t.sol:StakingManagerTest
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 2.72s (2.60s CPU time)
Ran 2 tests for test/TNFT.t.sol:TnftTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 26.33ms (2.99ms CPU time)
Ran 6 tests for test/TVLOracle.t.sol:TVLOracleTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 31.92ms (7.45ms CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferEth.t.sol:LiquidReferETHScrollTest
Suite result: FAILED. 0 passed; 4 failed; 0 skipped; finished in 3.86s (2.70s CPU time)
Ran 2 tests for test/integration-tests/Validator-Flows.t.sol:ValidatorFlowsIntegrationTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 9.34s (6.28s CPU time)
Ran 17 tests for test/WeETH.t.sol:WeETHTest
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 68.29ms (37.84ms CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferEth.t.sol:LiquidReferEthTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 3.47s (3.35s CPU time)
Ran 32 tests for test/WithdrawRequestNFT.t.sol:WithdrawRequestNFTTest
Suite result: ok. 32 passed; 0 failed; 0 skipped; finished in 5.93s (5.90s CPU time)
Ran 8 tests for test/integration-tests/Deposit.t.sol:DepositIntegrationTest
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 9.96s (9.85s CPU time)
Ran 6 tests for test/liquid-tests/LiquidReferUsdPermit.t.sol:LiquidReferUsdPermitScrollTest
Suite result: FAILED. 0 passed; 6 failed; 0 skipped; finished in 5.47s (4.36s CPU time)
Ran 6 tests for test/DepositAdapter.t.sol:DepositAdapterTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 5.82s (5.21s CPU time)
Ran 17 tests for test/EETH.t.sol:EETHTest
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 65.29ms (32.46ms CPU time)
Ran 6 tests for test/liquid-tests/LiquidReferUsdPermit.t.sol:LiquidReferUsdPermitTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 5.03s (4.84s CPU time)
Ran 11 tests for test/integration-tests/Withdraw.t.sol:WithdrawIntegrationTest
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 13.12s (9.79s CPU time)
Ran 4 tests for test/MembershipNFT.t.sol:MembershipNFTTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 28.17ms (5.53ms CPU time)
Ran 8 tests for test/NodeOperatorManager.t.sol:NodeOperatorManagerTest
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 34.26ms (11.70ms CPU time)
Ran 12 tests for test/liquid-tests/LiquidReferWhitelist.t.sol:LiquidReferWhitelistTest
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 2.77s (2.35s CPU time)
Ran 79 tests for test/LiquidityPool.t.sol:LiquidityPoolTest
Suite result: ok. 79 passed; 0 failed; 0 skipped; finished in 135.97ms (111.17ms CPU time)
Ran 1 test for test/behaviour-tests/pectra-fork-tests/EL-withdrawals.t.sol:ELExitsTest
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.57s (3.25s CPU time)
Ran 2 tests for test/behaviour-tests/ELExitsForkTestingDeployment.t.sol:ELExitsForkTestingDeploymentTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.65ms (179.80µs CPU time)
Ran 59 tests for test/PriorityWithdrawalQueue.t.sol:PriorityWithdrawalQueueTest
Suite result: ok. 59 passed; 0 failed; 0 skipped; finished in 8.71s (4.94s CPU time)
Ran 71 tests for test/EtherFiNodesManager.t.sol:EtherFiNodesManagerTest
Suite result: FAILED. 69 passed; 2 failed; 0 skipped; finished in 11.78s (8.28s CPU time)
Ran 7 tests for test/EtherFiOperationParameters.t.sol:EtherFiOperationParametersTest
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 421.73ms (413.57ms CPU time)
Ran 58 tests for test/EtherFiOracle.t.sol:EtherFiOracleTest
Suite result: ok. 58 passed; 0 failed; 0 skipped; finished in 150.07ms (127.57ms CPU time)
Ran 56 tests for test/EtherFiRateLimiter.t.sol:EtherFiRateLimiterTest
Suite result: ok. 56 passed; 0 failed; 0 skipped; finished in 948.56ms (946.37ms CPU time)
Ran 40 tests for test/behaviour-tests/prelude.t.sol:PreludeTest
Suite result: ok. 40 passed; 0 failed; 0 skipped; finished in 38.71s (33.42s CPU time)
Ran 24 tests for test/fork-tests/validator-key-gen.t.sol:ValidatorKeyGenTest
Suite result: ok. 24 passed; 0 failed; 0 skipped; finished in 9.07s (6.67s CPU time)
Ran 1 test for test/EtherFiViewer.t.sol:EtherFiViewerTest
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.20s (864.29ms CPU time)
Ran 10 tests for test/EtherFiRestaker.t.sol:EtherFiRestakerTest
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 28.97s (28.30s CPU time)
Ran 32 tests for test/EtherFiRewardsRouter.t.sol:EtherFiRewardsRouterTest
Suite result: ok. 32 passed; 0 failed; 0 skipped; finished in 14.47ms (11.96ms CPU time)
Ran 3 tests for test/integration-tests/Handle-Remainder-Shares.t.sol:HandleRemainderSharesIntegrationTest
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 7.29s (7.10s CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferBtc.t.sol:LiquidReferBtcScrollTest
Suite result: FAILED. 0 passed; 4 failed; 0 skipped; finished in 5.47s (3.07s CPU time)
Ran 6 tests for test/EtherFiTimelock.t.sol:TimelockTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 2.67s (6.16s CPU time)
Ran 14 tests for test/Liquifier.t.sol:LiquifierTest
Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 47.46s (51.22s CPU time)
Ran 41 tests for test/EtherFiRedemptionManager.t.sol:EtherFiRedemptionManagerTest
Suite result: ok. 41 passed; 0 failed; 0 skipped; finished in 38.25s (38.23s CPU time)
Ran 46 test suites in 77.83s (288.45s CPU time): 798 tests passed, 20 failed, 0 skipped (818 total tests)

Generated by workflow run #690

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a9198f0. Configure here.

keccak256("CONSOLIDATION_REQUEST_LIMIT_ID");

uint256 internal constant FULL_EXIT_GWEI = 2_048_000_000_000;
uint256 internal constant SECONDS_PER_DAY = 86_400;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unused SECONDS_PER_DAY constant in rate-limit scripts

Low Severity

SECONDS_PER_DAY is declared in both ReduceRateLimits.s.sol and RaiseRateLimits.s.sol but is never referenced in the code. The refill-rate divisions (e.g., 1_064_960_000_000_000 / 86_400) were computed offline and hardcoded as constants, leaving SECONDS_PER_DAY as dead code.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a9198f0. Configure here.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9198f0ad2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread script/utils/utils.sol
ICreate2Factory constant mainnetCreate2Factory = ICreate2Factory(0x356d1B83970CeF2018F2c9337cDdb67dff5AEF99);

uint256 constant MIN_DELAY_OPERATING_TIMELOCK = 28800; // 8 hours
uint256 constant MIN_DELAY_OPERATING_TIMELOCK = 172800; // 2 days
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep operating timelock delay aligned with production value

Changing MIN_DELAY_OPERATING_TIMELOCK from 28,800 to 172,800 in the shared Utils base alters every script that schedules through this constant to a 2-day delay, while the operational flow in this repo still assumes 8 hours (including the newly added whale-ops runbook). In practice this creates schedule/execute mismatches where execute transactions are attempted on the old window and revert as not-ready, delaying critical ops by an extra 40 hours. This shared constant should remain consistent with the actual timelock delay (or be read dynamically from getMinDelay()).

Useful? React with 👍 / 👎.

uint256 stEthAfter = IERC20(lido).balanceOf(address(restaker));
console2.log("stETH received:", stEthAfter - stEthBefore);

uint256 depositAmount = IERC20(lido).balanceOf(address(restaker));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid encoding a stale stETH deposit amount in STEP=2 batch

depositAmount is snapshotted during fork simulation and then hardcoded into the generated depositIntoStrategy calldata, but STEP=2 is executed later in production after a waiting period; if the restaker’s stETH balance changes in the meantime (e.g., redemptions or accounting drift), the batch can either fail on tx3 (insufficient balance) or leave funds undeployed. This makes the multi-tx redelegation flow brittle and should be replaced with a runtime balance-based deposit step.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant