Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delegation integration tests #358

Merged
merged 36 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fae2a60
test: add scenario 2 tests
ypatil12 Nov 20, 2023
c04f76d
test: move assertions into common functions
ypatil12 Nov 20, 2023
c81795f
test: add scenario 3
ypatil12 Nov 22, 2023
fa3d3cb
test: scaffold for scenario 4
ypatil12 Nov 29, 2023
5a5255c
test: add ETH support; add single test for scenario 4
ypatil12 Nov 30, 2023
e610ad2
test: address some comments
ypatil12 Dec 1, 2023
df125f7
test: address additional comments; all tests passing
ypatil12 Dec 1, 2023
70527a2
test: add separate withdrawal as tokens and shares methods
ypatil12 Dec 1, 2023
2361d27
fix: total strategy shares method naming
ypatil12 Dec 1, 2023
877ea71
test: add scenario 2 tests
ypatil12 Nov 20, 2023
7a3cedd
test: move assertions into common functions
ypatil12 Nov 20, 2023
d226820
test: add scenario 3
ypatil12 Nov 22, 2023
25b3e8d
test: add ETH support; add single test for scenario 4
ypatil12 Nov 30, 2023
9117006
test: deposit, queue, complete
Gajesh2007 Nov 30, 2023
60ebd9d
test: deposit, register as operator, queue and complete
Gajesh2007 Nov 30, 2023
01cd429
test: delegate, deposit, queue and complete
Gajesh2007 Nov 30, 2023
c017fa2
test: deposit, delegate, redelegate, complete
Gajesh2007 Dec 1, 2023
950eee3
update EigenPod unit and integration tests
ypatil12 Nov 6, 2023
fe80744
test: implement random withdrawal generator (#349)
wadealexc Nov 30, 2023
bd390fd
test: add scenario 2 tests
ypatil12 Nov 20, 2023
d75659e
test: move assertions into common functions
ypatil12 Nov 20, 2023
b6149e2
test: add ETH support; add single test for scenario 4
ypatil12 Nov 30, 2023
b915087
test: address some comments
ypatil12 Dec 1, 2023
616dcbd
test: address additional comments; all tests passing
ypatil12 Dec 1, 2023
0f80c8c
test: add separate withdrawal as tokens and shares methods
ypatil12 Dec 1, 2023
917aa89
test: update with new test framework
ypatil12 Dec 4, 2023
c4b62f8
test: remove commented test
ypatil12 Dec 4, 2023
a5f53f7
fix: remove extra function
ypatil12 Dec 4, 2023
28dbf5f
fix: added checks and other required changes
Gajesh2007 Dec 6, 2023
fb216a2
feat: additional deposit before
Gajesh2007 Dec 11, 2023
e3821d3
Merge branch 'm2-mainnet' into delegationIntegrationTests
Gajesh2007 Dec 11, 2023
15d0415
Update IntegrationBase.t.sol
Gajesh2007 Dec 11, 2023
4ff8dab
fix: added check_deposit_state_partialdeposit again
Gajesh2007 Dec 11, 2023
1760648
Scenario 4 Integration Tests (#375)
ypatil12 Dec 13, 2023
c2dd7aa
update Delegate_Deposit_Queue_Complete.t.sol
Gajesh2007 Dec 13, 2023
7a426a4
fix: fix delegate deposit test
ypatil12 Jan 2, 2024
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
6 changes: 5 additions & 1 deletion src/test/integration/IntegrationBase.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ abstract contract IntegrationBase is IntegrationDeployer {

function assert_Snap_Added_QueuedWithdrawal(
User staker,
IDelegationManager.Withdrawal memory withdrawal,
string memory err
) internal {
uint curQueuedWithdrawal = _getCumulativeWithdrawals(staker);
Expand Down Expand Up @@ -489,6 +490,9 @@ abstract contract IntegrationBase is IntegrationDeployer {
return (withdrawStrats, withdrawShares);
}

/**
* Helpful getters:
*/
function _randBalanceUpdate(
User staker,
IStrategy[] memory strategies
Expand Down Expand Up @@ -784,4 +788,4 @@ abstract contract IntegrationBase is IntegrationDeployer {

return shares;
}
}
}
56 changes: 41 additions & 15 deletions src/test/integration/IntegrationChecks.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ contract IntegrationCheckUtils is IntegrationBase {
// ... check that all underlying tokens were transferred to the correct destination
// and that the staker now has the expected amount of delegated shares in each strategy
assert_HasNoUnderlyingTokenBalance(staker, strategies, "staker should have transferred all underlying tokens");
assert_Snap_Added_StakerShares(staker, strategies, shares, "staker should expect shares in each strategy after depositing");
}


function check_Deposit_State_PartialDeposit(User staker, IStrategy[] memory strategies, uint[] memory shares, uint[] memory tokenBalances) internal {
/// Deposit into strategies:
// For each of the assets held by the staker (either StrategyManager or EigenPodManager),
// the staker calls the relevant deposit function, depositing some subset of held assets
//
// ... check that some underlying tokens were transferred to the correct destination
// and that the staker now has the expected amount of delegated shares in each strategy
assert_HasUnderlyingTokenBalances(staker, strategies, tokenBalances, "staker should have transferred some underlying tokens");
assert_Snap_Added_StakerShares(staker, strategies, shares, "staker should expected shares in each strategy after depositing");
}

Expand Down Expand Up @@ -81,6 +93,16 @@ contract IntegrationCheckUtils is IntegrationBase {
assert_Snap_Removed_StakerShares(staker, strategies, shares, "failed to remove staker shares");
}

/**
* @notice Overloaded function to check the state after a withdrawal as tokens, accepting a non-user type for the operator.
* @param staker The staker who completed the withdrawal.
* @param operator The operator address, which can be a non-user type like address(0).
* @param withdrawal The details of the withdrawal that was completed.
* @param strategies The strategies from which the withdrawal was made.
* @param shares The number of shares involved in the withdrawal.
* @param tokens The tokens received after the withdrawal.
* @param expectedTokens The expected tokens to be received after the withdrawal.
*/
function check_Withdrawal_AsTokens_State(
User staker,
User operator,
Expand All @@ -90,17 +112,19 @@ contract IntegrationCheckUtils is IntegrationBase {
IERC20[] memory tokens,
uint[] memory expectedTokens
) internal {
/// Complete withdrawal(s):
// The staker will complete the withdrawal as tokens
//
// ... check that the withdrawal is not pending, that the withdrawer received the expected tokens, and that the total shares of each
// strategy withdrawn decreases
// Common checks
assert_WithdrawalNotPending(delegationManager.calculateWithdrawalRoot(withdrawal), "staker withdrawal should no longer be pending");
assert_Snap_Added_TokenBalances(staker, tokens, expectedTokens, "staker should have received expected tokens");
assert_Snap_Unchanged_TokenBalances(operator, "operator token balances should not have changed");
assert_Snap_Unchanged_StakerShares(staker, "staker shares should not have changed");
assert_Snap_Unchanged_OperatorShares(operator, "operator shares should not have changed");
assert_Snap_Removed_StrategyShares(strategies, shares, "strategies should have total shares decremented");

// Checks specific to an operator that the Staker has delegated to
if (operator != User(payable(0))) {
if (operator != staker) {
assert_Snap_Unchanged_TokenBalances(User(operator), "operator token balances should not have changed");
}
assert_Snap_Unchanged_OperatorShares(User(operator), "operator shares should not have changed");
}
}

function check_Withdrawal_AsShares_State(
Expand All @@ -110,17 +134,19 @@ contract IntegrationCheckUtils is IntegrationBase {
IStrategy[] memory strategies,
uint[] memory shares
) internal {
/// Complete withdrawal(s):
// The staker will complete the withdrawal as shares
//
// ... check that the withdrawal is not pending, that the withdrawer received the expected shares, and that the total shares of each
// strategy withdrawn remains unchanged
// Common checks applicable to both user and non-user operator types
assert_WithdrawalNotPending(delegationManager.calculateWithdrawalRoot(withdrawal), "staker withdrawal should no longer be pending");
assert_Snap_Unchanged_TokenBalances(staker, "staker should not have any change in underlying token balances");
assert_Snap_Unchanged_TokenBalances(operator, "operator should not have any change in underlying token balances");
assert_Snap_Added_StakerShares(staker, strategies, shares, "staker should have received expected shares");
assert_Snap_Added_OperatorShares(operator, withdrawal.strategies, withdrawal.shares, "operator should have received shares");
assert_Snap_Unchanged_StrategyShares(strategies, "strategies should have total shares unchanged");

// Additional checks or handling for the non-user operator scenario
if (operator != User(User(payable(0)))) {
if (operator != staker) {
assert_Snap_Unchanged_TokenBalances(User(operator), "operator should not have any change in underlying token balances");
}
assert_Snap_Added_OperatorShares(User(operator), withdrawal.strategies, withdrawal.shares, "operator should have received shares");
}
}

/// @notice Difference from above is that operator shares do not increase since staker is not delegated
Expand All @@ -144,4 +170,4 @@ contract IntegrationCheckUtils is IntegrationBase {
assert_Snap_Unchanged_OperatorShares(operator, "operator should have shares unchanged");
assert_Snap_Unchanged_StrategyShares(strategies, "strategies should have total shares unchanged");
}
}
}
81 changes: 81 additions & 0 deletions src/test/integration/tests/Delegate_Deposit_Queue_Complete.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;

import "src/test/integration/IntegrationChecks.t.sol";
import "src/test/integration/User.t.sol";

contract Integration_Delegate_Deposit_QueueWithdrawal_Complete is IntegrationCheckUtils {

function testFuzz_delegate_deposit_queueWithdrawal_completeAsShares(uint24 _random) public {
// Configure the random parameters for the test
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS
});

// Create a staker and an operator with a nonzero balance and corresponding strategies
(User staker, IStrategy[] memory strategies, uint[] memory tokenBalances) = _newRandomStaker();
(User operator, ,) = _newRandomOperator();

// 1. Delegate to operator
staker.delegateTo(operator);
check_Delegation_State(staker, operator, strategies, new uint256[](strategies.length)); // Initial shares are zero

// 2. Deposit into strategy
staker.depositIntoEigenlayer(strategies, tokenBalances);
uint[] memory shares = _calculateExpectedShares(strategies, tokenBalances);

// Check that the deposit increased operator shares the staker is delegated to
check_Delegation_State(staker, operator, strategies, shares);
ypatil12 marked this conversation as resolved.
Show resolved Hide resolved

// 3. Queue Withdrawal
IDelegationManager.Withdrawal[] memory withdrawals = staker.queueWithdrawals(strategies, shares);
bytes32[] memory withdrawalRoots = _getWithdrawalHashes(withdrawals);
check_QueuedWithdrawal_State(staker, operator, strategies, shares, withdrawals, withdrawalRoots);

// 4. Complete Queued Withdrawal
cheats.roll(block.number + delegationManager.withdrawalDelayBlocks());
for (uint i = 0; i < withdrawals.length; i++) {
staker.completeWithdrawalAsShares(withdrawals[i]);
check_Withdrawal_AsShares_State(staker, operator, withdrawals[i], strategies, shares);
}
}

function testFuzz_delegate_deposit_queueWithdrawal_completeAsTokens(uint24 _random) public {
// Configure the random parameters for the test
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS
});

// Create a staker and an operator with a nonzero balance and corresponding strategies
(User staker, IStrategy[] memory strategies, uint[] memory tokenBalances) = _newRandomStaker();
(User operator, ,) = _newRandomOperator();

// 1. Delegate to operator
staker.delegateTo(operator);
check_Delegation_State(staker, operator, strategies, new uint256[](strategies.length)); // Initial shares are zero

// 2. Deposit into strategy
staker.depositIntoEigenlayer(strategies, tokenBalances);
uint[] memory shares = _calculateExpectedShares(strategies, tokenBalances);

// Check that the deposit increased operator shares the staker is delegated to
check_Delegation_State(staker, operator, strategies, shares);

// 3. Queue Withdrawal
IDelegationManager.Withdrawal[] memory withdrawals = staker.queueWithdrawals(strategies, shares);
bytes32[] memory withdrawalRoots = _getWithdrawalHashes(withdrawals);
check_QueuedWithdrawal_State(staker, operator, strategies, shares, withdrawals, withdrawalRoots);

// 4. Complete Queued Withdrawal
cheats.roll(block.number + delegationManager.withdrawalDelayBlocks());
for (uint i = 0; i < withdrawals.length; i++) {
uint[] memory expectedTokens = _calculateExpectedTokens(strategies, shares);
IERC20[] memory tokens = staker.completeWithdrawalAsTokens(withdrawals[i]);
check_Withdrawal_AsTokens_State(staker, operator, withdrawals[i], strategies, shares, tokens, expectedTokens);
}
}
}
Loading
Loading