Skip to content

test: checkpoint with no added shares#1191

Merged
8sunyuan merged 3 commits intotest/slashing-integration-testingfrom
test/checkpoint-noaddedshares
Mar 4, 2025
Merged

test: checkpoint with no added shares#1191
8sunyuan merged 3 commits intotest/slashing-integration-testingfrom
test/checkpoint-noaddedshares

Conversation

@8sunyuan
Copy link
Copy Markdown
Contributor

Motivation:

EigenPodManager.recordBeaconChainETHBalanceUpdate currently has a bug where shares increases of 0 addedShares will forward a call to the DelegationManager and updates the DSF. This can be manipulated to increase your DSF and inflate a staker's inflatable shares. The test in this PR demonstrates a possible exploit scenario.

Modifications:

Added test file Integration_CompleteCP_WithNoAddedShares and integration test test_completeCP_withNoAddedShares

Setup is as follows:

  1. Setup a Staker EigenPod where they are initially slashed and have a non-WAD BCSF
  2. Queue withdraw all deposit shares setting it to 0
  3. Start/Complete checkpoints with 0 addedShares
    • This triggers the following code block in SlashingLib.sol when updating the DSF and increases the staker's DSF
if (prevDepositShares == 0) {
    // If this is the staker's first deposit or they are delegating to an operator,
    // the slashing factor is inverted and applied to the existing DSF. This has the
    // effect of "forgiving" prior slashing for any subsequent deposits.
    dsf._scalingFactor = dsf.scalingFactor().divWad(slashingFactor);
    return;
}
  1. Deposit again (in this case complete withdrawals as shares from step 3)
  2. Delegate to an Operator

Staker ends up having inflated withdrawable shares and as a result is able to delegate way more share than they should be able to for an operator.

Result:

After this issue is fixed, this integration test should pass

@0xClandestine 0xClandestine added 🗡️ Slashing Release Changes for the slashing release. 🧪 Test Test-related changes (unit, integration, etc.). labels Feb 28, 2025
@ypatil12
Copy link
Copy Markdown
Contributor

Can we merge this into the fix PR?

@8sunyuan
Copy link
Copy Markdown
Contributor Author

#1176
@ypatil12 this one right?

@8sunyuan 8sunyuan force-pushed the test/checkpoint-noaddedshares branch from 8d72593 to e9e2d71 Compare March 4, 2025 18:01
@8sunyuan 8sunyuan force-pushed the test/checkpoint-noaddedshares branch from fe396dd to 254a8f1 Compare March 4, 2025 21:41
Copy link
Copy Markdown
Contributor

@ypatil12 ypatil12 left a comment

Choose a reason for hiding this comment

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

LGTM, one clarifying comment

(uint256[] memory withdrawableSharesAfter, uint256[] memory depositSharesAfter) = delegationManager.getWithdrawableShares(address(staker), strategies);
assertEq(depositSharesAfter[0], initDelegatableShares[0], "Deposit shares should reset to reflect slash(es)");
assertApproxEqAbs(withdrawableSharesAfter[0], depositSharesAfter[0], 100, "Withdrawable shares should equal deposit shares after withdrawal");
assertApproxEqAbs(withdrawableSharesAfter[0], depositSharesAfter[0], 1000, "Withdrawable shares should equal deposit shares after withdrawal");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Assume this check is sanity? Since we do assert_Snap_Added_Staker_WithdrawableShares in the complete as shares check.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There were some instances where it was failing with a real delta of 103. Perhaps because my added contract is inheriting the other tests

@8sunyuan 8sunyuan merged commit b855ea8 into test/slashing-integration-testing Mar 4, 2025
10 checks passed
@8sunyuan 8sunyuan deleted the test/checkpoint-noaddedshares branch March 4, 2025 22:05
ypatil12 pushed a commit that referenced this pull request Mar 5, 2025
<!-- 
    🚨 ATTENTION! 🚨 
    
This PR template is REQUIRED. PRs not following this format will be
closed without review.
    
    Requirements:
- PR title must follow commit conventions:
https://www.conventionalcommits.org/en/v1.0.0/
- Label your PR with the correct type (e.g., 🐛 Bug, ✨ Enhancement, 🧪
Test, etc.)
    - Provide clear and specific details in each section
-->

**Motivation:**

`EigenPodManager.recordBeaconChainETHBalanceUpdate` currently has a bug
where shares increases of 0 addedShares will forward a call to the
DelegationManager and updates the DSF. This can be manipulated to
increase your DSF and inflate a staker's inflatable shares. The test in
this PR demonstrates a possible exploit scenario.

**Modifications:**

Added test file `Integration_CompleteCP_WithNoAddedShares` and
integration test `test_completeCP_withNoAddedShares`

Setup is as follows:
1. Setup a Staker EigenPod where they are initially slashed and have a
non-WAD BCSF
2. Queue withdraw all deposit shares setting it to 0
3. Start/Complete checkpoints with 0 addedShares
- This triggers the following code block in `SlashingLib.sol` when
updating the DSF and increases the staker's DSF
```
if (prevDepositShares == 0) {
    // If this is the staker's first deposit or they are delegating to an operator,
    // the slashing factor is inverted and applied to the existing DSF. This has the
    // effect of "forgiving" prior slashing for any subsequent deposits.
    dsf._scalingFactor = dsf.scalingFactor().divWad(slashingFactor);
    return;
}
```
4. Deposit again (in this case complete withdrawals as shares from step
3)
5. Delegate to an Operator

Staker ends up having inflated withdrawable shares and as a result is
able to delegate way more share than they should be able to for an
operator.


**Result:**

After this issue is fixed, this integration test should pass
ypatil12 pushed a commit that referenced this pull request Mar 5, 2025
<!-- 
    🚨 ATTENTION! 🚨 
    
This PR template is REQUIRED. PRs not following this format will be
closed without review.
    
    Requirements:
- PR title must follow commit conventions:
https://www.conventionalcommits.org/en/v1.0.0/
- Label your PR with the correct type (e.g., 🐛 Bug, ✨ Enhancement, 🧪
Test, etc.)
    - Provide clear and specific details in each section
-->

**Motivation:**

`EigenPodManager.recordBeaconChainETHBalanceUpdate` currently has a bug
where shares increases of 0 addedShares will forward a call to the
DelegationManager and updates the DSF. This can be manipulated to
increase your DSF and inflate a staker's inflatable shares. The test in
this PR demonstrates a possible exploit scenario.

**Modifications:**

Added test file `Integration_CompleteCP_WithNoAddedShares` and
integration test `test_completeCP_withNoAddedShares`

Setup is as follows:
1. Setup a Staker EigenPod where they are initially slashed and have a
non-WAD BCSF
2. Queue withdraw all deposit shares setting it to 0
3. Start/Complete checkpoints with 0 addedShares
- This triggers the following code block in `SlashingLib.sol` when
updating the DSF and increases the staker's DSF
```
if (prevDepositShares == 0) {
    // If this is the staker's first deposit or they are delegating to an operator,
    // the slashing factor is inverted and applied to the existing DSF. This has the
    // effect of "forgiving" prior slashing for any subsequent deposits.
    dsf._scalingFactor = dsf.scalingFactor().divWad(slashingFactor);
    return;
}
```
4. Deposit again (in this case complete withdrawals as shares from step
3)
5. Delegate to an Operator

Staker ends up having inflated withdrawable shares and as a result is
able to delegate way more share than they should be able to for an
operator.


**Result:**

After this issue is fixed, this integration test should pass
ypatil12 added a commit that referenced this pull request Mar 5, 2025
**Motivation:**

Slashing Integration Testing for Competition Audit

**Modifications:**

***General State Validation***
- #1204
- #1198
- #1169
- #1158

***Upgrade Tests***
- #1187
- #1171
- #1143

***Dual Slash Tests***
- #1195
- #1153

***Rounding Tests***
- #1178

***EigenPod Tests***
- #1191
- #1188
- #1203
- #1194
- #1163

***Invariants***
- #1201
- #1176
- #1192
- #1197
- #1175
- #1189
- #1150
- #1149

**Result:**

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

Labels

🗡️ Slashing Release Changes for the slashing release. 🧪 Test Test-related changes (unit, integration, etc.).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants