Skip to content

Priority withdrawal queue#356

Open
pankajjagtapp wants to merge 50 commits intomasterfrom
pankaj/feat/priority-withdrawal-queue
Open

Priority withdrawal queue#356
pankajjagtapp wants to merge 50 commits intomasterfrom
pankaj/feat/priority-withdrawal-queue

Conversation

@pankajjagtapp
Copy link
Contributor

@pankajjagtapp pankajjagtapp commented Jan 28, 2026

Note

High Risk
High risk because it introduces a new upgradeable withdrawal flow that can lock ETH and changes LiquidityPool.withdraw/EtherFiRedemptionManager liquidity calculations, directly impacting user withdrawals and redemption availability.

Overview
Adds a new upgradeable PriorityWithdrawalQueue contract for whitelisted “priority” withdrawals (request/finalize/claim, permit + weETH support, pausing, role-gated whitelist and request management, and remainder-share handling).

Integrates the queue into core withdrawal paths by upgrading LiquidityPool and EtherFiRedemptionManager: both gain a priorityWithdrawalQueue immutable, LiquidityPool.withdraw/burnEEthShares accept calls from the queue and enforce separate liquidity reservations, and EtherFiRedemptionManager.getInstantLiquidityAmount(ETH) now subtracts priority-locked ETH.

Adds deployment/upgrade tooling and artifacts (Create2 deploy script + timelock transaction generator, operation-parameter update script + Gnosis JSON, new mainnet address constant, deployment logs), updates create2 deploy helper to be idempotent, and adds extensive tests for the priority queue and updated LiquidityPool constructor usage.

Written by Cursor Bugbot for commit 3c5d76b. This will update automatically on new commits. Configure here.

…al request handling and treasury fee distribution

- Rename and adjust constants for clarity
- Introduce immutable treasury address and share remainder split to treasury
- Simplify withdrawal request structure by removing unnecessary parameters
- Enhance request management with new roles and functions for invalidating requests
- Update event emissions and error handling for better clarity and functionality
…drawalQueue and remove setter function

- Change priorityWithdrawalQueue to an immutable variable initialized in the constructor
- Remove the setPriorityWithdrawalQueue function to enhance security and restrict modifications
- Adjust reduceEthAmountLockedForPriorityWithdrawal to allow only the priorityWithdrawalQueue to call it
…improved initialization and request handling
- Change nonce and minDelay types to uint32 for better compatibility
- Adjust withdrawal request structure to use consistent data types
- Update event emissions and function signatures to reflect new types
- Enhance role management for whitelist operations
@pankajjagtapp pankajjagtapp self-assigned this Jan 28, 2026
Copy link
Contributor

@seongyun-ko seongyun-ko left a comment

Choose a reason for hiding this comment

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

Nice work! :)

  1. why do we need 'withdrawCapacity'? we can just let them submit whatever they want and handle from our end?

  2. let's put Reentrancy Protection to (requestWithdraw, cancelWithdraw, claimWithdraw)

  3. let's put guards so that (requestWithdraw) and (cancelWithdraw, claimWithdraw) can't happen within the same block in any case. preveting any possible loop. saw 'minDelay' config.

  4. as a post-hook, let's add balance check of (LiquidityPool/PriorityWithdrawalQueue), so that it reverts if unexpected balance change occurs

…ved withdrawal handling

- Update burnEEthShares function to include priorityWithdrawalQueue as a valid caller
- Refactor withdrawal logic to calculate and return the lesser of original amount or current share value, addressing negative rebase scenarios
- Adjust event emissions to reflect updated withdrawal amounts and shares transferred
- Remove withdrawal configuration struct and related functions for clarity
- Introduce constants for minimum delay and minimum withdrawal amount
- Enhance request handling with new post-condition verification methods
- Update tests to reflect changes in withdrawal logic and configuration
@pankajjagtapp pankajjagtapp force-pushed the pankaj/feat/priority-withdrawal-queue branch from 0b80857 to f199f40 Compare January 28, 2026 20:13
- Replace constant MIN_DELAY with an immutable variable initialized in the constructor
- Adjust withdrawal request handling to check for MIN_DELAY in a more efficient manner
- Update tests to reflect changes in constructor parameters and request validation logic
Copy link
Contributor

@vvalecha519 vvalecha519 left a comment

Choose a reason for hiding this comment

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

  1. U will need to make changes to EtherFiRedemptionManager (ie. getInstantLiquidityAmount needs to get eth locked by priority queue as well)

  2. Maybe add easy way to query a users pending wds... pain-point with veda's on chain queue?

…dant comments and simplifying logic

- Removed unnecessary comments and documentation for clarity
- Streamlined canceling withdrawal request handling by directly using request parameters
- Enhanced event emissions to reflect accurate withdrawal amounts and shares
@pankajjagtapp pankajjagtapp added the enhancement New feature or request label Jan 28, 2026
Copy link

@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 3 potential issues.

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

Signed-off-by: Pankaj Jagtap <jagtap.pankaj2000@gmail.com>
@github-actions
Copy link

github-actions bot commented Feb 26, 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 2 tests for test/behaviour-tests/ELExitsForkTestingDeployment.t.sol:ELExitsForkTestingDeploymentTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 2.18ms (199.96µs CPU time)
Ran 5 tests for test/AddressProvider.t.sol:AddressProviderTest
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 41.93ms (6.35ms CPU time)
Ran 23 tests for test/AuctionManager.t.sol:AuctionManagerTest
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 54.95ms (34.59ms CPU time)
Ran 2 tests for test/BNFT.t.sol:BNFTTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 23.39ms (2.23ms CPU time)
Ran 58 tests for test/BucketRaterLimiter.t.sol:BucketRateLimiterTest
Suite result: ok. 58 passed; 0 failed; 0 skipped; finished in 26.72ms (25.30ms CPU time)
Ran 2 tests for test/fork-tests/pectra-fork-tests/Consolidation-through-EOA.sol:ConsolidationThroughEOATest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 834.12ms (541.78ms CPU time)
Ran 2 tests for test/ContractCodeChecker.t.sol:ContractCodeCheckerTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 77.36ms (39.89ms CPU time)
Ran 3 tests for test/behaviour-tests/pectra-fork-tests/Request-consolidation.t.sol:RequestConsolidationTest
Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.07s (629.36ms CPU time)
Ran 27 tests for test/RestakingRewardsRouter.t.sol:RestakingRewardsRouterTest
Suite result: ok. 27 passed; 0 failed; 0 skipped; finished in 15.47ms (12.07ms CPU time)
Ran 9 tests for test/RoleRegistry.t.sol:RoleRegistryTest
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 3.83ms (2.70ms CPU time)
Ran 9 tests for test/CumulativeMerkleRewardsDistributor.t.sol:CumulativeMerkleRewardsDistributorTest
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 47.44ms (16.90ms CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferBtc.t.sol:LiquidReferBtcTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 1.37s (1.19s CPU time)
Ran 21 tests for test/StakingManager.t.sol:StakingManagerTest
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 597.48ms (559.51ms CPU time)
Ran 2 tests for test/TNFT.t.sol:TnftTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 23.91ms (2.79ms CPU time)
Ran 6 tests for test/TVLOracle.t.sol:TVLOracleTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 28.92ms (6.88ms CPU time)
Ran 71 tests for test/EtherFiNodesManager.t.sol:EtherFiNodesManagerTest
Suite result: ok. 71 passed; 0 failed; 0 skipped; finished in 2.09s (1.24s CPU time)
Ran 2 tests for test/integration-tests/Validator-Flows.t.sol:ValidatorFlowsIntegrationTest
Suite result: FAILED. 1 passed; 1 failed; 0 skipped; finished in 626.16ms (494.34ms CPU time)
Ran 17 tests for test/WeETH.t.sol:WeETHTest
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 50.45ms (28.97ms CPU time)
Ran 7 tests for test/EtherFiOperationParameters.t.sol:EtherFiOperationParametersTest
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 430.31ms (423.10ms CPU time)
Ran 8 tests for test/integration-tests/Deposit.t.sol:DepositIntegrationTest
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 1.48s (1.46s CPU time)
Ran 58 tests for test/EtherFiOracle.t.sol:EtherFiOracleTest
Suite result: ok. 58 passed; 0 failed; 0 skipped; finished in 133.70ms (110.24ms CPU time)
Ran 6 tests for test/DepositAdapter.t.sol:DepositAdapterTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 157.11ms (96.20ms CPU time)
Ran 17 tests for test/EETH.t.sol:EETHTest
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 63.31ms (29.03ms CPU time)
Ran 2 tests for test/behaviour-tests/pectra-fork-tests/EL-withdrawals.t.sol:ELExitsTest
Suite result: FAILED. 1 passed; 1 failed; 0 skipped; finished in 76.96ms (33.26ms CPU time)
Ran 12 tests for test/liquid-tests/LiquidReferWhitelist.t.sol:LiquidReferWhitelistTest
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 393.03ms (353.32ms CPU time)
Ran 11 tests for test/integration-tests/Withdraw.t.sol:WithdrawIntegrationTest
Suite result: FAILED. 6 passed; 5 failed; 0 skipped; finished in 951.57ms (916.34ms CPU time)
Ran 79 tests for test/LiquidityPool.t.sol:LiquidityPoolTest
Suite result: ok. 79 passed; 0 failed; 0 skipped; finished in 138.15ms (114.93ms CPU time)
Ran 56 tests for test/EtherFiRateLimiter.t.sol:EtherFiRateLimiterTest
Suite result: ok. 56 passed; 0 failed; 0 skipped; finished in 1.01s (1.01s CPU time)
Ran 14 tests for test/Liquifier.t.sol:LiquifierTest
Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 2.70s (2.69s CPU time)
Ran 4 tests for test/MembershipNFT.t.sol:MembershipNFTTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 27.53ms (5.17ms CPU time)
Ran 8 tests for test/NodeOperatorManager.t.sol:NodeOperatorManagerTest
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 34.85ms (11.71ms CPU time)
Ran 32 tests for test/WithdrawRequestNFT.t.sol:WithdrawRequestNFTTest
Suite result: ok. 32 passed; 0 failed; 0 skipped; finished in 2.86s (2.82s CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferEth.t.sol:LiquidReferETHScrollTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 5.17s (4.46s CPU time)
Ran 59 tests for test/PriorityWithdrawalQueue.t.sol:PriorityWithdrawalQueueTest
Suite result: ok. 59 passed; 0 failed; 0 skipped; finished in 764.32ms (581.36ms CPU time)
Ran 41 tests for test/EtherFiRedemptionManager.t.sol:EtherFiRedemptionManagerTest
Suite result: ok. 41 passed; 0 failed; 0 skipped; finished in 3.64s (3.62s CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferEth.t.sol:LiquidReferEthTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 907.71ms (872.91ms 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 578.95ms (480.61ms CPU time)
Ran 10 tests for test/EtherFiRestaker.t.sol:EtherFiRestakerTest
Suite result: ok. 10 passed; 0 failed; 0 skipped; finished in 1.19s (1.14s CPU time)
Ran 32 tests for test/EtherFiRewardsRouter.t.sol:EtherFiRewardsRouterTest
Suite result: ok. 32 passed; 0 failed; 0 skipped; finished in 13.55ms (11.24ms CPU time)
Ran 6 tests for test/EtherFiTimelock.t.sol:TimelockTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 857.40ms (1.04s CPU time)
Ran 1 test for test/EtherFiViewer.t.sol:EtherFiViewerTest
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 135.15ms (82.97ms CPU time)
Ran 6 tests for test/liquid-tests/LiquidReferUsdPermit.t.sol:LiquidReferUsdPermitTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 2.08s (2.04s 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 2.68s (1.14s CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferBtc.t.sol:LiquidReferBtcScrollTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 4.37s (7.41s CPU time)
Ran 6 tests for test/liquid-tests/LiquidReferUsdPermit.t.sol:LiquidReferUsdPermitScrollTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 7.03s (8.03s CPU time)
Ran 40 tests for test/behaviour-tests/prelude.t.sol:PreludeTest
Suite result: ok. 40 passed; 0 failed; 0 skipped; finished in 7.75s (5.05s CPU time)
Ran 46 test suites in 13.99s (54.61s CPU time): 812 tests passed, 7 failed, 0 skipped (819 total tests)

Generated by workflow run #667

Copy link

@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 3 potential issues.

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

@etherfi-protocol etherfi-protocol deleted a comment from github-actions bot Feb 27, 2026
Copy link

@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 3 potential issues.

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

Copy link

@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.

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

Copy link

@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 2 potential issues.

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

solipsis
solipsis previously approved these changes Mar 2, 2026
Copy link

@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 2 potential issues.

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

@pankajjagtapp pankajjagtapp force-pushed the pankaj/feat/priority-withdrawal-queue branch from edf486a to 0ba348c Compare March 3, 2026 19:21
Copy link

@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 2 potential issues.

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

Copy link

@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 2 potential issues.

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

Copy link

@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 2 potential issues.

Fix All in Cursor

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

if (priorityWithdrawalQueue != address(0)) {
uint128 priorityLocked = uint128(IPriorityWithdrawalQueue(priorityWithdrawalQueue).ethAmountLockedForPriorityWithdrawal());
if (totalValueInLp - priorityLocked < _amount) revert InsufficientLiquidity();
}
Copy link

Choose a reason for hiding this comment

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

NFT withdrawal cross-reserve check is too weak

Medium Severity

The NFT withdrawal path checks totalValueInLp - priorityLocked >= _amount, but the correct invariant to maintain is totalValueInLp >= ethAmountLockedForWithdrawal + priorityLocked. When _amount is smaller than ethAmountLockedForWithdrawal (a partial claim of one NFT from many), the check is too lenient and allows withdrawals that leave the LP unable to serve remaining NFT and priority obligations combined. This breaks the cross-reserve isolation that this PR intends to enforce.

Fix in Cursor Fix in Web

function getInstantLiquidityAmount(address token) public view returns (uint256) {
if(token == ETH_ADDRESS) {
return address(liquidityPool).balance - liquidityPool.ethAmountLockedForWithdrawal();
return address(liquidityPool).balance - liquidityPool.ethAmountLockedForWithdrawal() - priorityWithdrawalQueue.ethAmountLockedForPriorityWithdrawal();
Copy link

Choose a reason for hiding this comment

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

Potential underflow in getInstantLiquidityAmount breaks redemptions

Medium Severity

getInstantLiquidityAmount subtracts both ethAmountLockedForWithdrawal() and ethAmountLockedForPriorityWithdrawal() from the LP balance. Since these two locks are managed by independent actors (EtherFiAdmin and the priority queue request manager) with no combined cap enforcement, their sum can exceed address(liquidityPool).balance, causing an underflow revert. This would break canRedeem, totalRedeemableAmount, and redeem for ETH entirely—not gracefully returning zero but reverting.

Fix in Cursor Fix in Web

Copy link

@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 3 potential issues.

Fix All in Cursor

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

if (_amount > type(uint128).max || _amount == 0 || share == 0) revert InvalidAmount();

totalValueInLp -= uint128(_amount);
if (msg.sender == priorityWithdrawalQueue && (totalValueInLp - ethAmountLockedForWithdrawal < _amount)) revert InsufficientLiquidity();
Copy link

Choose a reason for hiding this comment

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

Arithmetic underflow in LP withdraw lock checks

High Severity

The subtraction totalValueInLp - ethAmountLockedForWithdrawal (line 225) and totalValueInLp - priorityLocked (line 231) can underflow, causing a panic revert instead of the intended InsufficientLiquidity error. Since membershipManager and etherFiRedemptionManager callers pass through withdraw() without respecting either lock, they can drain totalValueInLp below the lock values. This would then DoS subsequent NFT and priority queue withdrawals with an unexpected panic revert.

Additional Locations (1)
Fix in Cursor Fix in Web

function getInstantLiquidityAmount(address token) public view returns (uint256) {
if(token == ETH_ADDRESS) {
return address(liquidityPool).balance - liquidityPool.ethAmountLockedForWithdrawal();
return address(liquidityPool).balance - liquidityPool.ethAmountLockedForWithdrawal() - priorityWithdrawalQueue.ethAmountLockedForPriorityWithdrawal();
Copy link

Choose a reason for hiding this comment

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

Underflow in getInstantLiquidityAmount breaks instant redemptions

Medium Severity

The expression address(liquidityPool).balance - liquidityPool.ethAmountLockedForWithdrawal() - priorityWithdrawalQueue.ethAmountLockedForPrior ityWithdrawal() can underflow and revert if the LP's actual ETH balance is less than the sum of both lock amounts. Since membershipManager withdrawals reduce the LP balance without respecting either lock, this view function can become permanently reverting, blocking all instant redemptions via totalRedeemableAmount.

Fix in Cursor Fix in Web

emit WithdrawRequestFinalized(requestId, request.user, request.amountOfEEth, request.shareOfEEth, request.nonce, uint32(block.timestamp));
}

ethAmountLockedForPriorityWithdrawal += uint128(totalAmountToLock);
Copy link

Choose a reason for hiding this comment

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

Fulfills lock amountOfEEth but only withdraws amountWithFee

Medium Severity

fulfillRequests locks request.amountOfEEth in ethAmountLockedForPriorityWithdrawal, but _claimWithdraw only actually withdraws request.amountWithFee (which can be significantly less due to fees). The lock is then decremented by amountOfEEth on claim, so it balances out per-request, but while requests are pending, the over-locked amount unnecessarily restricts NFT queue withdrawals and instant redemptions that check this value.

Additional Locations (1)
Fix in Cursor Fix in Web

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants