Skip to content

feat: New roles for Restaker, Bug Fixes#375

Open
pankajjagtapp wants to merge 27 commits intomasterfrom
pankaj/feat/new-roles-for-restaker
Open

feat: New roles for Restaker, Bug Fixes#375
pankajjagtapp wants to merge 27 commits intomasterfrom
pankaj/feat/new-roles-for-restaker

Conversation

@pankajjagtapp
Copy link
Copy Markdown
Contributor

@pankajjagtapp pankajjagtapp commented Mar 18, 2026

Note

High Risk
High risk because it changes access control and rate limiting on EtherFiRestaker withdrawal/strategy flows and modifies EtherFiRedemptionManager ETH transfer behavior and fee accounting, which directly impacts mainnet funds movement and upgrade execution.

Overview
Introduces per-function roles and rate limiting for EtherFiRestaker. Admin-gated stETH/EigenLayer actions (stEthRequestWithdrawal, stEthClaimWithdrawals, queueWithdrawals, completeQueuedWithdrawals, depositIntoStrategy) now require specific RoleRegistry roles and consume from new EtherFiRateLimiter buckets; the restaker constructor adds immutable roleRegistry/rateLimiter, and a new redelegate helper is added.

Tightens redemption and referral edge cases. EtherFiRedemptionManager increases the ETH transfer gas stipend (10k→100k) and sweeps any residual eETH dust to treasury, updating the Redeemed event fee field accordingly; LiquidRefer now handles fee-on-transfer tokens by using the actual received amount and makes permit best-effort.

Adds upgrade/ops automation and updates tests/config. New scripts deploy/execute a timelock batch upgrade (including role grants and rate limiter setup) and generate Safe JSONs; the stETH-claim ops script also outputs Safe JSON. Tests are updated for the new constructor/roles/limiters, add coverage for redelegate and limiter behavior, adjust redemption liquidity expectations, and temporarily skip some fork tests; foundry.toml consolidates fs_permissions for scripts.

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

@pankajjagtapp pankajjagtapp self-assigned this Mar 18, 2026
@pankajjagtapp pankajjagtapp added the enhancement New feature or request label Mar 18, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 18, 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                     | 89.47% (51/57)     | 93.85% (61/65)     | 72.73% (8/11)    | 77.78% (7/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           | 44.87% (70/156)    | 44.51% (77/173)    | 24.14% (14/58)   | 54.55% (18/33)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| src/EtherFiRestaker.sol                    | 83.24% (144/173)   | 85.38% (181/212)   | 32.00% (8/25)    | 63.89% (23/36)   |
|--------------------------------------------+--------------------+--------------------+------------------+------------------|
| 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                                      | 72.27% (2220/3072) | 70.51% (2410/3418) | 59.63% (486/815) | 72.39% (493/681) |

---
Ran 2 tests for test/behaviour-tests/ELExitsForkTestingDeployment.t.sol:ELExitsForkTestingDeploymentTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 5.29ms (211.43µs CPU time)
Ran 5 tests for test/AddressProvider.t.sol:AddressProviderTest
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 45.90ms (8.81ms CPU time)
Ran 23 tests for test/AuctionManager.t.sol:AuctionManagerTest
Suite result: ok. 23 passed; 0 failed; 0 skipped; finished in 65.50ms (39.01ms CPU time)
Ran 2 tests for test/BNFT.t.sol:BNFTTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 25.67ms (2.67ms CPU time)
Ran 58 tests for test/BucketRaterLimiter.t.sol:BucketRateLimiterTest
Suite result: ok. 58 passed; 0 failed; 0 skipped; finished in 32.86ms (30.65ms CPU time)
Ran 1 test for test/fork-tests/pectra-fork-tests/Consolidation-through-EOA.sol:ConsolidationThroughEOATest
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 744.61ms (367.48ms CPU time)
Ran 2 tests for test/ContractCodeChecker.t.sol:ContractCodeCheckerTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 78.46ms (29.00ms CPU time)
Ran 9 tests for test/CumulativeMerkleRewardsDistributor.t.sol:CumulativeMerkleRewardsDistributorTest
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 39.22ms (14.49ms CPU time)
Ran 69 tests for test/EtherFiNodesManager.t.sol:EtherFiNodesManagerTest
Suite result: ok. 69 passed; 0 failed; 0 skipped; finished in 2.20s (1.21s 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.27s (1.23s CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferBtc.t.sol:LiquidReferBtcScrollTest
Suite result: FAILED. 0 passed; 4 failed; 0 skipped; finished in 2.35s (1.67s CPU time)
Ran 7 tests for test/DepositAdapter.t.sol:DepositAdapterTest
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 235.95ms (139.34ms CPU time)
Ran 17 tests for test/EETH.t.sol:EETHTest
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 51.07ms (26.39ms CPU time)
Ran 7 tests for test/EtherFiOperationParameters.t.sol:EtherFiOperationParametersTest
Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 489.57ms (481.47ms 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 148.42ms (93.11ms CPU time)
Ran 58 tests for test/EtherFiOracle.t.sol:EtherFiOracleTest
Suite result: ok. 58 passed; 0 failed; 0 skipped; finished in 157.51ms (132.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 1.54s (1.50s CPU time)
Ran 56 tests for test/EtherFiRateLimiter.t.sol:EtherFiRateLimiterTest
Suite result: ok. 56 passed; 0 failed; 0 skipped; finished in 1.24s (1.24s CPU time)
Ran 59 tests for test/PriorityWithdrawalQueue.t.sol:PriorityWithdrawalQueueTest
Suite result: ok. 59 passed; 0 failed; 0 skipped; finished in 1.18s (805.74ms CPU time)
Ran 27 tests for test/RestakingRewardsRouter.t.sol:RestakingRewardsRouterTest
Suite result: ok. 27 passed; 0 failed; 0 skipped; finished in 13.62ms (9.70ms CPU time)
Ran 9 tests for test/RoleRegistry.t.sol:RoleRegistryTest
Suite result: ok. 9 passed; 0 failed; 0 skipped; finished in 3.35ms (2.30ms CPU time)
Ran 41 tests for test/EtherFiRedemptionManager.t.sol:EtherFiRedemptionManagerTest
Suite result: ok. 41 passed; 0 failed; 0 skipped; finished in 4.49s (4.45s CPU time)
Ran 21 tests for test/StakingManager.t.sol:StakingManagerTest
Suite result: ok. 21 passed; 0 failed; 0 skipped; finished in 621.05ms (604.53ms CPU time)
Ran 2 tests for test/TNFT.t.sol:TnftTest
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 28.66ms (2.52ms CPU time)
Ran 6 tests for test/TVLOracle.t.sol:TVLOracleTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 32.41ms (7.34ms CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferEth.t.sol:LiquidReferETHScrollTest
Suite result: FAILED. 0 passed; 4 failed; 0 skipped; finished in 1.47s (1.35s 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 813.07ms (502.08ms CPU time)
Ran 17 tests for test/WeETH.t.sol:WeETHTest
Suite result: ok. 17 passed; 0 failed; 0 skipped; finished in 64.54ms (33.97ms CPU time)
Ran 11 tests for test/integration-tests/Withdraw.t.sol:WithdrawIntegrationTest
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 404.36ms (363.94ms 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.17s (2.14s CPU time)
Ran 12 tests for test/liquid-tests/LiquidReferWhitelist.t.sol:LiquidReferWhitelistTest
Suite result: ok. 12 passed; 0 failed; 0 skipped; finished in 44.78ms (15.00ms CPU time)
Ran 79 tests for test/LiquidityPool.t.sol:LiquidityPoolTest
Suite result: ok. 79 passed; 0 failed; 0 skipped; finished in 161.99ms (128.08ms CPU time)
Ran 4 tests for test/liquid-tests/LiquidReferEth.t.sol:LiquidReferEthTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 1.35s (1.31s CPU time)
Ran 26 tests for test/EtherFiRestaker.t.sol:EtherFiRestakerTest
Suite result: FAILED. 23 passed; 3 failed; 0 skipped; finished in 2.39s (1.78s CPU time)
Ran 32 tests for test/EtherFiRewardsRouter.t.sol:EtherFiRewardsRouterTest
Suite result: ok. 32 passed; 0 failed; 0 skipped; finished in 13.24ms (11.06ms CPU time)
Ran 6 tests for test/EtherFiTimelock.t.sol:TimelockTest
Suite result: ok. 6 passed; 0 failed; 0 skipped; finished in 582.03ms (727.56ms CPU time)
Ran 1 test for test/EtherFiViewer.t.sol:EtherFiViewerTest
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 151.86ms (97.63ms CPU time)
Ran 32 tests for test/WithdrawRequestNFT.t.sol:WithdrawRequestNFTTest
Suite result: ok. 32 passed; 0 failed; 0 skipped; finished in 2.74s (2.71s 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 1.24s (1.21s CPU time)
Ran 4 tests for test/MembershipNFT.t.sol:MembershipNFTTest
Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 28.58ms (5.27ms CPU time)
Ran 8 tests for test/NodeOperatorManager.t.sol:NodeOperatorManagerTest
Suite result: ok. 8 passed; 0 failed; 0 skipped; finished in 38.16ms (11.14ms 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 775.70ms (1.25s CPU time)
Ran 6 tests for test/liquid-tests/LiquidReferUsdPermit.t.sol:LiquidReferUsdPermitScrollTest
Suite result: FAILED. 0 passed; 6 failed; 0 skipped; finished in 3.19s (2.53s CPU time)
Ran 14 tests for test/Liquifier.t.sol:LiquifierTest
Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 3.78s (3.81s CPU time)
Ran 40 tests for test/behaviour-tests/prelude.t.sol:PreludeTest
Suite result: ok. 40 passed; 0 failed; 0 skipped; finished in 2.50s (4.98s CPU time)
Ran 45 test suites in 11.27s (41.01s CPU time): 812 tests passed, 17 failed, 0 skipped (829 total tests)

Generated by workflow run #683

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: 2afe3b8ad6

ℹ️ 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/upgrades/restaker-roles/transactions.s.sol Outdated
Comment thread src/EtherFiRestaker.sol Outdated
Comment thread src/EtherFiRestaker.sol
Comment thread script/upgrades/restaker-roles/transactions.s.sol Outdated
…Safe transaction JSON for claimable requests and integrate Utils for improved functionality
…ransactions, enhance tests for EtherFiRestaker withdrawal limits
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 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Deploy script missing fourth constructor argument for rateLimiter
    • Added ETHERFI_RATE_LIMITER as the fourth argument in the deploy script's abi.encode call to match the EtherFiRestaker constructor signature.
  • ✅ Resolved by another fix: Deploy script missing rateLimiter constructor argument
    • This bug is a duplicate of bug 551a8061 and was resolved by the same fix that added ETHERFI_RATE_LIMITER to the constructor arguments.

Create PR

Or push these changes by commenting:

@cursor push 4c4748d125
Preview (4c4748d125)
diff --git a/script/upgrades/restaker-roles/deploy.s.sol b/script/upgrades/restaker-roles/deploy.s.sol
--- a/script/upgrades/restaker-roles/deploy.s.sol
+++ b/script/upgrades/restaker-roles/deploy.s.sol
@@ -9,7 +9,7 @@
  * @title DeployEtherFiRestakerWithRoles
  * @notice Deploys the new EtherFiRestaker implementation with per-function RoleRegistry roles
  *
- * Constructor now takes a third arg: _roleRegistry
+ * Constructor now takes a fourth arg: _rateLimiter
  *
  * Command:
  * forge script script/upgrades/restaker-roles/deploy.s.sol --fork-url $MAINNET_RPC_URL -vvvv
@@ -32,7 +32,8 @@
             bytes memory constructorArgs = abi.encode(
                 EIGENLAYER_REWARDS_COORDINATOR,
                 ETHERFI_REDEMPTION_MANAGER,
-                ROLE_REGISTRY
+                ROLE_REGISTRY,
+                ETHERFI_RATE_LIMITER
             );
             bytes memory bytecode = abi.encodePacked(
                 type(EtherFiRestaker).creationCode,

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Comment thread script/upgrades/restaker-roles/deploy.s.sol
Comment thread script/upgrades/restaker-roles/deploy.s.sol
Comment thread script/upgrades/restaker-roles/transactions.s.sol
Comment thread script/upgrades/restaker-roles/transactions.s.sol
…itate large stETH redemptions, including transaction scheduling and execution JSON files
…lesTransactions with fork tests for role-based access control and redemption manager configuration
Comment thread src/EtherFiRestaker.sol Outdated
Comment thread script/upgrades/restaker-roles/transactions.s.sol
@pankajjagtapp pankajjagtapp changed the title feat: Deposit Adapter new functions, New roles for Restaker feat: New roles for Restaker, Bug Fixes Mar 24, 2026
…ount instead of requested amount, ensuring accurate share calculations and referral emissions
… redemption, ensuring efficient fund management
Comment thread script/operations/steth-management/ClaimStEthWithdrawals.s.sol
… limiter and associated tests for improved rate limiting functionality
…ered withdrawal and request consolidation. kept for easier reference
…plementation and enhance stETH funding logic for improved testing efficiency
…tions for deployment and upgrade verification
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.

bytes32 bufferedEtherPos = keccak256("lido.Lido.bufferedEther");

// AragonOS mapping lookup: keccak256(encodePacked(key, position))
bytes32 accountSlot = keccak256(abi.encodePacked(to, sharesMapPos));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wrong storage slot computation in _dealStETH helper

Medium Severity

The _dealStETH function uses abi.encodePacked(to, sharesMapPos) to compute the AragonOS shares mapping slot, producing a 52-byte hash input (20-byte address + 32-byte position). AragonOS's getStorageMapping uses assembly (mstore(0x00, key)) which left-pads the address to 32 bytes, yielding a 64-byte input — equivalent to abi.encode(to, sharesMapPos). This mismatch means vm.store writes to the wrong slot, so the restaker's stETH balance is never actually set. The testDepositIntoStrategyRateLimit fork test, which calls _dealStETH, will therefore fail or produce incorrect results, undermining upgrade verification.

Fix in Cursor Fix in Web

…d tests for operator management and withdrawal tracking
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.

1 participant