Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/test/integration/IntegrationBase.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1995,11 +1995,12 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
/// @dev On a delegation, the DSF should be increased if the operator magnitude is non-WAD
function assert_Snap_DSF_State_Delegation(
User staker,
User operator,
IStrategy[] memory strategies,
uint[] memory delegatableShares,
string memory err
) internal {
uint64[] memory maxMags = _getMaxMagnitudes(staker, strategies);
uint64[] memory maxMags = _getMaxMagnitudes(operator, strategies);

for (uint i = 0; i < strategies.length; i++) {
IStrategy[] memory stratArray = strategies[i].toArray();
Expand Down
2 changes: 1 addition & 1 deletion src/test/integration/IntegrationChecks.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ contract IntegrationCheckUtils is IntegrationBase {
uint256[] memory delegatableShares = _getPrevStakerWithdrawableShares(staker, strategies);
assert_Snap_Added_OperatorShares(operator, strategies, delegatableShares, "operator should have received shares");
check_Added_SlashableStake(operator, strategies, delegatableShares);
assert_Snap_DSF_State_Delegation(staker, strategies, delegatableShares, "staker's DSF not updated correctly");
assert_Snap_DSF_State_Delegation(staker, operator, strategies, delegatableShares, "staker's DSF not updated correctly");
}

function check_Added_SlashableStake(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ contract Integration_Deposit_Delegate_Allocate_Slash_Queue_Redeposit is Integrat
uint[] numTokensRemaining;

function _init() internal override {
// TODO: Partial deposits don't work when beacon chain eth balance is initialized to < 64 ETH, need to write _newRandomStaker variant that ensures beacon chain ETH balance
// greater than or equal to 64
_configAssetTypes(HOLDS_LST);
_configUserTypes(DEFAULT);

(staker, strategies, initTokenBalances) = _newRandomStaker();
Expand All @@ -33,9 +30,14 @@ contract Integration_Deposit_Delegate_Allocate_Slash_Queue_Redeposit is Integrat

uint[] memory tokensToDeposit = new uint[](initTokenBalances.length);
numTokensRemaining = new uint[](initTokenBalances.length);
uint256 eth_to_deal;
for (uint i = 0; i < initTokenBalances.length; i++) {
if (strategies[i] == BEACONCHAIN_ETH_STRAT) {
tokensToDeposit[i] = initTokenBalances[i];
//user.depositIntoEigenlayer uses all ETH balance for a pod, so we deal back staker's
//starting ETH to replicate partial deposit state
eth_to_deal = initTokenBalances[i];
numTokensRemaining[i] = initTokenBalances[i];
continue;
}

Expand All @@ -46,6 +48,8 @@ contract Integration_Deposit_Delegate_Allocate_Slash_Queue_Redeposit is Integrat
// 1. Deposit Into Strategies
initDepositShares = _calculateExpectedShares(strategies, tokensToDeposit);
staker.depositIntoEigenlayer(strategies, tokensToDeposit);
//dealing back ETH
cheats.deal(address(staker), eth_to_deal);
check_Deposit_State_PartialDeposit(staker, strategies, initDepositShares, numTokensRemaining);

// 2. Delegate to operator
Expand Down Expand Up @@ -302,4 +306,79 @@ contract Integration_Deposit_Delegate_Allocate_Slash_Queue_Redeposit is Integrat
operator.modifyAllocations(deallocateParams);
check_DecrAlloc_State_Slashable(operator, deallocateParams);
}

function testFuzz_fullSlash_undelegate_redeposit_complete(
uint24 _random
) public rand(_random) {

initDepositShares = _getStakerDepositShares(staker, strategies);

// 4. Fully slash operator
SlashingParams memory slashParams = _genSlashing_Full(operator, operatorSet);
avs.slashOperator(slashParams);
check_FullySlashed_State(operator, allocateParams, slashParams);

// 5. Undelegate from an operator
uint[] memory withdrawableShares = _getStakerWithdrawableShares(staker, strategies);
Withdrawal[] memory withdrawals = staker.undelegate();
bytes32[] memory withdrawalRoots = _getWithdrawalHashes(withdrawals);
check_Undelegate_State(staker, operator, withdrawals, withdrawalRoots, strategies, withdrawableShares);

// 6. Redeposit
uint[] memory shares = _calculateExpectedShares(strategies, numTokensRemaining);
staker.depositIntoEigenlayer(strategies, numTokensRemaining);
check_Deposit_State(staker, strategies, shares);

// 7. Complete withdrawal. Staker should receive 0 shares/tokens after a full slash
_rollBlocksForCompleteWithdrawals(withdrawals);

for (uint256 i = 0; i < withdrawals.length; ++i) {
uint[] memory expectedShares = _calculateExpectedShares(withdrawals[i]);
staker.completeWithdrawalAsShares(withdrawals[i]);
check_Withdrawal_AsShares_Undelegated_State(staker, operator, withdrawals[i], withdrawals[i].strategies, expectedShares);
}


// Final state checks
assert_HasExpectedShares(staker, strategies, shares, "staker should have expected shares after redeposit");
assert_NoWithdrawalsPending(withdrawalRoots, "all withdrawals should be removed from pending");
}

function testFuzz_fullSlash_redelegate_redeposit_complete(
uint24 _random
) public rand(_random) {

(User operator2, ,) = _newRandomOperator();
initDepositShares = _getStakerDepositShares(staker, strategies);

// 4. Fully slash operator
SlashingParams memory slashParams = _genSlashing_Full(operator, operatorSet);
avs.slashOperator(slashParams);
check_FullySlashed_State(operator, allocateParams, slashParams);

// 5. Undelegate from an operator
uint[] memory withdrawableShares = _getStakerWithdrawableShares(staker, strategies);
Withdrawal[] memory withdrawals = staker.redelegate(operator2);
bytes32[] memory withdrawalRoots = _getWithdrawalHashes(withdrawals);
check_Redelegate_State(staker, operator, operator2, withdrawals, withdrawalRoots, strategies, withdrawableShares);

// 6. Redeposit
uint[] memory shares = _calculateExpectedShares(strategies, numTokensRemaining);
staker.depositIntoEigenlayer(strategies, numTokensRemaining);
check_Deposit_State(staker, strategies, shares);

// 7. Complete withdrawal. Staker should receive 0 shares/tokens after a full slash
_rollBlocksForCompleteWithdrawals(withdrawals);

for (uint256 i = 0; i < withdrawals.length; ++i) {
uint[] memory expectedShares = _calculateExpectedShares(withdrawals[i]);
staker.completeWithdrawalAsShares(withdrawals[i]);
check_Withdrawal_AsShares_Undelegated_State(staker, operator, withdrawals[i], withdrawals[i].strategies, expectedShares);
}


// Final state checks
assert_HasExpectedShares(staker, strategies, shares, "staker should have expected shares after redeposit");
assert_NoWithdrawalsPending(withdrawalRoots, "all withdrawals should be removed from pending");
}
}
127 changes: 63 additions & 64 deletions src/test/integration/tests/Slashed_Eigenpod_BC.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -130,72 +130,71 @@ contract Integration_SlashedEigenpod_BC is IntegrationCheckUtils {
assertApproxEqAbs(withdrawableSharesAfter[0], depositSharesAfter[0], 100, "Withdrawable shares should equal deposit shares after withdrawal");
}

// TODO: Fix this test
// function testFuzz_delegateSlashedStaker_slashedOperator(uint24 _random) public rand(_random) {


// (User staker2,,) = _newRandomStaker();
// (uint40[] memory validators2,) = staker2.startValidators();
// beaconChain.advanceEpoch_NoWithdrawNoRewards();
// staker2.verifyWithdrawalCredentials(validators2);
// staker2.startCheckpoint();
// staker2.completeCheckpoint();
// staker2.delegateTo(operator);

// //randomize additional deposit to eigenpod
// if(_randBool()){
// uint amount = 32 ether * _randUint({min: 1, max: 5});
// cheats.deal(address(staker), amount);
// (uint40[] memory validators,) = staker.startValidators();
// beaconChain.advanceEpoch_NoWithdrawNoRewards();
// staker.verifyWithdrawalCredentials(validators);
function testFuzz_delegateSlashedStaker_slashedOperator(uint24 _random) public rand(_random) {


(User staker2,,) = _newRandomStaker();
(uint40[] memory validators2,) = staker2.startValidators();
beaconChain.advanceEpoch_NoWithdrawNoRewards();
staker2.verifyWithdrawalCredentials(validators2);
staker2.startCheckpoint();
staker2.completeCheckpoint();
staker2.delegateTo(operator);

//randomize additional deposit to eigenpod
if(_randBool()){
uint amount = 32 ether * _randUint({min: 1, max: 5});
cheats.deal(address(staker), amount);
(uint40[] memory validators,) = staker.startValidators();
beaconChain.advanceEpoch_NoWithdrawNoRewards();
staker.verifyWithdrawalCredentials(validators);

// staker.startCheckpoint();
// staker.completeCheckpoint();
// }

// // Create an operator set and register an operator.
// operatorSet = avs.createOperatorSet(strategies);
// operator.registerForOperatorSet(operatorSet);
// check_Registration_State_NoAllocation(operator, operatorSet, strategies);

// // Allocate to operator set
// allocateParams = _genAllocation_AllAvailable(operator, operatorSet, strategies);
// operator.modifyAllocations(allocateParams);
// check_IncrAlloc_State_Slashable(operator, allocateParams);
// _rollBlocksForCompleteAllocation(operator, operatorSet, strategies);

// //Slash operator before delegation
// IAllocationManagerTypes.SlashingParams memory slashingParams;
// uint wadToSlash = _randWadToSlash();
// slashingParams = avs.slashOperator(operator, operatorSet.id, strategies, wadToSlash.toArrayU256());
// assert_Snap_Allocations_Slashed(slashingParams, operatorSet, true, "operator allocations should be slashed");

// uint256[] memory initDelegatableShares = _getWithdrawableShares(staker, strategies);
// uint256[] memory initDepositShares = _getStakerDepositShares(staker, strategies);

// // Delegate to an operator
// staker.delegateTo(operator);
// (uint256[] memory delegatedShares, ) = delegationManager.getWithdrawableShares(address(staker), strategies);
// check_Delegation_State(staker, operator, strategies, initDepositShares);
staker.startCheckpoint();
staker.completeCheckpoint();
}

// Create an operator set and register an operator.
operatorSet = avs.createOperatorSet(strategies);
operator.registerForOperatorSet(operatorSet);
check_Registration_State_NoAllocation(operator, operatorSet, strategies);

// Allocate to operator set
allocateParams = _genAllocation_AllAvailable(operator, operatorSet, strategies);
operator.modifyAllocations(allocateParams);
check_IncrAlloc_State_Slashable(operator, allocateParams);
_rollBlocksForCompleteAllocation(operator, operatorSet, strategies);

//Slash operator before delegation
IAllocationManagerTypes.SlashingParams memory slashingParams;
uint wadToSlash = _randWadToSlash();
slashingParams = avs.slashOperator(operator, operatorSet.id, strategies, wadToSlash.toArrayU256());
assert_Snap_Allocations_Slashed(slashingParams, operatorSet, true, "operator allocations should be slashed");

uint256[] memory initDelegatableShares = _getWithdrawableShares(staker, strategies);
uint256[] memory initDepositShares = _getStakerDepositShares(staker, strategies);

// Delegate to an operator
staker.delegateTo(operator);
(uint256[] memory delegatedShares, ) = delegationManager.getWithdrawableShares(address(staker), strategies);
check_Delegation_State(staker, operator, strategies, initDepositShares);

// // Undelegate from an operator
// IDelegationManagerTypes.Withdrawal[] memory withdrawals = staker.undelegate();
// bytes32[] memory withdrawalRoots = _getWithdrawalHashes(withdrawals);
// check_Undelegate_State(staker, operator, withdrawals, withdrawalRoots, strategies, initDepositShares, delegatedShares);

// // Complete withdrawal as shares
// // Fast forward to when we can complete the withdrawal
// _rollBlocksForCompleteWithdrawals(withdrawals);
// for (uint256 i = 0; i < withdrawals.length; ++i) {
// staker.completeWithdrawalAsShares(withdrawals[i]);
// check_Withdrawal_AsShares_Undelegated_State(staker, operator, withdrawals[i], withdrawals[i].strategies, delegatedShares);
// }

// (uint256[] memory withdrawableSharesAfter, uint256[] memory depositSharesAfter) = delegationManager.getWithdrawableShares(address(staker), strategies);
// assertEq(depositSharesAfter[0], delegatedShares[0], "Deposit shares should reset to reflect slash(es)");
// assertApproxEqAbs(withdrawableSharesAfter[0], depositSharesAfter[0], 100, "Withdrawable shares should equal deposit shares after withdrawal");
// }
// Undelegate from an operator
IDelegationManagerTypes.Withdrawal[] memory withdrawals = staker.undelegate();
bytes32[] memory withdrawalRoots = _getWithdrawalHashes(withdrawals);
check_Undelegate_State(staker, operator, withdrawals, withdrawalRoots, strategies, delegatedShares);

// Complete withdrawal as shares
// Fast forward to when we can complete the withdrawal
_rollBlocksForCompleteWithdrawals(withdrawals);
for (uint256 i = 0; i < withdrawals.length; ++i) {
staker.completeWithdrawalAsShares(withdrawals[i]);
check_Withdrawal_AsShares_Undelegated_State(staker, operator, withdrawals[i], withdrawals[i].strategies, delegatedShares);
}

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

function testFuzz_delegateSlashedStaker_redelegate_complete(uint24 _random) public rand(_random){

Expand Down
1 change: 0 additions & 1 deletion src/test/integration/tests/SlashingWithdrawals.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ contract Integration_ALMSlashBase is IntegrationCheckUtils {
/// 5. Operator registers for operator set
/// NOTE: Steps 4 and 5 are done in random order, as these should not have an outcome on the test
function _init() internal virtual override {
_configAssetTypes(HOLDS_LST);
(staker, strategies, initTokenBalances) = _newRandomStaker();
operator = _newRandomOperator_NoAssets();
(avs,) = _newRandomAVS();
Expand Down
Loading