Skip to content

Commit

Permalink
refactor and rename and make EPM work
Browse files Browse the repository at this point in the history
  • Loading branch information
gpsanant committed Oct 4, 2024
1 parent 710ab45 commit 8f0e116
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 198 deletions.
7 changes: 4 additions & 3 deletions src/contracts/core/AllocationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,11 @@ contract AllocationManager is
// 2. update totalMagnitude, get total magnitude and subtract slashedMagnitude
// this will be reflected in the conversion of delegatedShares to shares in the DM
Snapshots.History storage totalMagnitudes = _totalMagnitudeUpdate[operator][strategies[i]];
totalMagnitudes.push({key: uint32(block.timestamp), value: totalMagnitudes.latest() - slashedMagnitude});
uint64 totalMagnitudeBeforeSlashing = uint64(totalMagnitudes.latest());
totalMagnitudes.push({key: uint32(block.timestamp), value: totalMagnitudeBeforeSlashing - slashedMagnitude});

//3. Update operators shares in the DM
delegation.updateOperatorShares(operator, strategies[i], uint64(totalMagnitudes.latest()));
// 3. Decrease operators shares in the DM
delegation.decreaseOperatorShares(operator, strategies[i], totalMagnitudeBeforeSlashing, uint64(totalMagnitudes.latest()));
}
}

Expand Down
91 changes: 34 additions & 57 deletions src/contracts/core/DelegationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,12 @@ contract DelegationManager is

for (uint256 i = 0; i < strategies.length; i++) {
IStrategy[] memory singleStrategy = new IStrategy[](1);
uint256[] memory singleOwnedShare = new uint256[](1);
uint256[] memory singleShares = new uint256[](1);
uint64[] memory singleTotalMagnitude = new uint64[](1);
singleStrategy[0] = strategies[i];
// TODO: this part is a bit gross, can we make it better?
singleOwnedShare[0] = SlashingLib.depositSharesToShares(
depositedShares[i],
stakerDepositScalingFactor[staker][strategies[i]],
singleShares[0] = depositedShares[i].toShares(
stakerScalingFactor[staker][strategies[i]],
totalMagnitudes[i]
);
singleTotalMagnitude[0] = totalMagnitudes[i];
Expand All @@ -292,13 +291,13 @@ contract DelegationManager is
staker: staker,
operator: operator,
strategies: singleStrategy,
sharesToWithdraw: singleOwnedShare,
sharesToWithdraw: singleShares,
totalMagnitudes: singleTotalMagnitude
});

// all shares and queued withdrawn and no delegated operator
// reset staker's depositScalingFactor to default
stakerDepositScalingFactor[staker][strategies[i]].depositScalingFactor = WAD;
stakerScalingFactor[staker][strategies[i]].depositScalingFactor = WAD;
}
}

Expand Down Expand Up @@ -433,7 +432,7 @@ contract DelegationManager is
// decrease the staker's beaconChainScalingFactor proportionally
// forgefmt: disable-next-item

stakerDepositScalingFactor[staker][beaconChainETHStrategy].decreaseBeaconChainScalingFactor(proportionOfOldBalance);
stakerScalingFactor[staker][beaconChainETHStrategy].decreaseBeaconChainScalingFactor(proportionOfOldBalance);

// if the staker is delegated to an operators
if (isDelegated(staker)) {
Expand All @@ -455,11 +454,12 @@ contract DelegationManager is
* @notice Decreases the operators shares in storage after a slash
* @param operator The operator to decrease shares for
* @param strategy The strategy to decrease shares for
* @param newMagnitude The new magnitude to decrease shares by
* @param previousMagnitude The magnitude before the slash
* @param newMagnitude The magnitude after the slash
* @dev Callable only by the AllocationManager
*/
function updateOperatorShares(address operator, IStrategy strategy, uint64 newMagnitude) external onlyAllocationManager {
operatorShares[operator][strategy] = SlashingLib.getOperatorSharesAfterSlash(operatorShares[operator][strategy], newMagnitude);
function decreaseOperatorShares(address operator, IStrategy strategy, uint64 previousMagnitude, uint64 newMagnitude) external onlyAllocationManager {
operatorShares[operator][strategy] = operatorShares[operator][strategy].decreaseOperatorShares(previousMagnitude, newMagnitude);
}

/**
Expand Down Expand Up @@ -582,9 +582,8 @@ contract DelegationManager is

for (uint256 i = 0; i < withdrawal.strategies.length; i++) {
IShareManager shareManager = _getShareManager(withdrawal.strategies[i]);
uint256 sharesToWithdraw = SlashingLib.scaleSharesForCompleteWithdrawal(
withdrawal.scaledSharesToWithdraw[i],
stakerDepositScalingFactor[withdrawal.staker][withdrawal.strategies[i]],
uint256 sharesToWithdraw = withdrawal.scaledSharesToWithdraw[i].scaleSharesForCompleteWithdrawal(
stakerScalingFactor[withdrawal.staker][withdrawal.strategies[i]],
totalMagnitudes[i]
);

Expand All @@ -596,15 +595,15 @@ contract DelegationManager is
staker: withdrawal.staker,
strategy: withdrawal.strategies[i],
token: tokens[i],
depositShares: sharesToWithdraw
shares: sharesToWithdraw
});
} else {
// Award shares back in StrategyManager/EigenPodManager.
shareManager.addDepositShares({
shareManager.addShares({
staker: withdrawal.staker,
strategy: withdrawal.strategies[i],
token: tokens[i],
depositShares: sharesToWithdraw
shares: sharesToWithdraw
});
}
}
Expand Down Expand Up @@ -633,15 +632,22 @@ contract DelegationManager is
uint64 totalMagnitude
) internal {
//TODO: double check ordering here
operatorShares[operator][strategy] += SlashingLib.depositSharesToShares(addedDepositShares, stakerDepositScalingFactor[staker][strategy], totalMagnitude);
operatorShares[operator][strategy] += addedDepositShares.toShares(stakerScalingFactor[staker][strategy], totalMagnitude);

_updateDepositScalingFactor({
staker: staker,
strategy: strategy,
existingDepositShares: existingDepositShares,
addedDepositShares: addedDepositShares,
totalMagnitude: totalMagnitude
});
uint256 newDepositScalingFactor;
if (existingDepositShares == 0) {
newDepositScalingFactor = WAD / totalMagnitude;
} else {
newDepositScalingFactor = SlashingLib.calculateNewDepositScalingFactor(
existingDepositShares,
addedDepositShares,
stakerScalingFactor[staker][strategy],
totalMagnitude
);
}

// update the staker's depositScalingFactor
stakerScalingFactor[staker][strategy].depositScalingFactor = newDepositScalingFactor;

// TODO: What to do about event wrt scaling?
emit OperatorSharesIncreased(operator, staker, strategy, addedDepositShares);
Expand Down Expand Up @@ -688,7 +694,7 @@ contract DelegationManager is
for (uint256 i = 0; i < strategies.length; ++i) {
IShareManager shareManager = _getShareManager(strategies[i]);

uint256 depositSharesToRemove = SlashingLib.withdrawableSharesToDepositShares(sharesToWithdraw[i], stakerDepositScalingFactor[staker][strategies[i]], totalMagnitudes[i]);
uint256 depositSharesToRemove = sharesToWithdraw[i].toDepositShares(stakerScalingFactor[staker][strategies[i]], totalMagnitudes[i]);
// TODO: maybe have a getter to get shares for all strategies,
// check sharesToWithdraw is valid
// but for inputted strategies
Expand All @@ -705,7 +711,7 @@ contract DelegationManager is
operatorSharesToDecrease: sharesToWithdraw[i]
});
}
scaledSharesToWithdraw[i] = SlashingLib.scaleSharesForQueuedWithdrawal(sharesToWithdraw[i], stakerDepositScalingFactor[staker][strategies[i]], totalMagnitudes[i]);
scaledSharesToWithdraw[i] = sharesToWithdraw[i].scaleSharesForQueuedWithdrawal(stakerScalingFactor[staker][strategies[i]], totalMagnitudes[i]);

// Remove active shares from EigenPodManager/StrategyManager
// EigenPodManager: this call will revert if it would reduce the Staker's virtual beacon chain ETH shares below zero
Expand Down Expand Up @@ -760,34 +766,6 @@ contract DelegationManager is
*
*/

/**
* @notice helper to calculate the new depositScalingFactor after adding shares. This is only used
* when a staker is depositing through the StrategyManager or EigenPodManager. A staker's depositScalingFactor
* is only updated when they have new deposits and their shares are being increased.
*/
function _updateDepositScalingFactor(
address staker,
IStrategy strategy,
uint64 totalMagnitude,
uint256 existingDepositShares,
uint256 addedDepositShares
) internal {
uint256 newDepositScalingFactor;
if (existingDepositShares == 0) {
newDepositScalingFactor = WAD / totalMagnitude;
} else {
newDepositScalingFactor = SlashingLib.calculateNewDepositScalingFactor(
existingDepositShares,
addedDepositShares,
stakerDepositScalingFactor[staker][strategy],
totalMagnitude
);
}

// update the staker's depositScalingFactor
stakerDepositScalingFactor[staker][strategy].depositScalingFactor = newDepositScalingFactor;
}

function _getShareManager(
IStrategy strategy
) internal view returns (IShareManager) {
Expand Down Expand Up @@ -887,9 +865,8 @@ contract DelegationManager is
uint64 totalMagnitude = allocationManager.getTotalMagnitude(operator, strategies[i]);

// forgefmt: disable-next-item
withdrawableShares[i] = SlashingLib.depositSharesToShares(
depositShares,
stakerDepositScalingFactor[staker][strategies[i]],
withdrawableShares[i] = depositShares.toShares(
stakerScalingFactor[staker][strategies[i]],
totalMagnitude
);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/core/DelegationManagerStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ abstract contract DelegationManagerStorage is IDelegationManager {
/// beacon chain scaling factor used to calculate the staker's withdrawable shares in the strategy.
/// )
/// Note that we don't need the beaconChainScalingFactor for non beaconChainETHStrategy strategies, but it's nicer syntactically to keep it.
mapping(address => mapping(IStrategy => StakerScalingFactors)) public stakerDepositScalingFactor;
mapping(address => mapping(IStrategy => StakerScalingFactors)) public stakerScalingFactor;

constructor(
IStrategyManager _strategyManager,
Expand Down
54 changes: 27 additions & 27 deletions src/contracts/core/StrategyManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -160,19 +160,19 @@ contract StrategyManager is
}

/// @notice Used by the DelegationManager to remove a Staker's shares from a particular strategy when entering the withdrawal queue
function removeDepositShares(address staker, IStrategy strategy, uint256 sharesToRemove) external onlyDelegationManager {
_removeDepositedShares(staker, strategy, sharesToRemove);
function removeDepositShares(address staker, IStrategy strategy, uint256 depositSharesToRemove) external onlyDelegationManager {
_removeDepositShares(staker, strategy, depositSharesToRemove);
}

/// @notice Used by the DelegationManager to award a Staker some shares that have passed through the withdrawal queue
/// @dev Specifically, this function is called when a withdrawal is completed as shares.
function addDepositShares(
function addShares(
address staker,
IStrategy strategy,
IERC20 token,
uint256 depositShares
uint256 shares
) external onlyDelegationManager {
_addDepositedShares(staker, token, strategy, depositShares);
_addShares(staker, token, strategy, shares);
}

/// @notice Used by the DelegationManager to convert withdrawn shares to tokens and send them to a recipient
Expand All @@ -182,9 +182,9 @@ contract StrategyManager is
address staker,
IStrategy strategy,
IERC20 token,
uint256 depositShares
uint256 shares
) external onlyDelegationManager {
strategy.withdraw(staker, token, depositShares);
strategy.withdraw(staker, token, shares);
}

/**
Expand Down Expand Up @@ -238,15 +238,15 @@ contract StrategyManager is
* @param staker The address to add shares to
* @param token The token that is being deposited (used for indexing)
* @param strategy The Strategy in which the `staker` is receiving shares
* @param depositedSharesToAdd The amount of shares to grant to the `staker`
* @param shares The amount of shares to grant to the `staker`
* @dev In particular, this function calls `delegation.increaseDelegatedShares(staker, strategy, shares)` to ensure that all
* delegated shares are tracked, increases the stored share amount in `stakerDepositShares[staker][strategy]`, and adds `strategy`
* to the `staker`'s list of strategies, if it is not in the list already.
*/
function _addDepositedShares(address staker, IERC20 token, IStrategy strategy, uint256 depositedSharesToAdd) internal {
function _addShares(address staker, IERC20 token, IStrategy strategy, uint256 shares) internal {
// sanity checks on inputs
require(staker != address(0), StakerAddressZero());
require(depositedSharesToAdd != 0, SharesAmountZero());
require(shares != 0, SharesAmountZero());

uint256 existingShares = stakerDepositShares[staker][strategy];

Expand All @@ -257,17 +257,17 @@ contract StrategyManager is
}

// add the returned depositedShares to their existing shares for this strategy
stakerDepositShares[staker][strategy] = existingShares + depositedSharesToAdd;
stakerDepositShares[staker][strategy] = existingShares + shares;

// Increase shares delegated to operator, if needed
delegation.increaseDelegatedShares({
staker: staker,
strategy: strategy,
existingDepositShares: existingShares,
addedDepositShares: depositedSharesToAdd
addedShares: shares
});

emit Deposit(staker, token, strategy, depositedSharesToAdd);
emit Deposit(staker, token, strategy, shares);
}

/**
Expand All @@ -277,50 +277,50 @@ contract StrategyManager is
* @param strategy The Strategy contract to deposit into.
* @param token The ERC20 token to deposit.
* @param amount The amount of `token` to deposit.
* @return depositedShares The amount of *new* shares in `strategy` that have been credited to the `staker`.
* @return shares The amount of *new* shares in `strategy` that have been credited to the `staker`.
*/
function _depositIntoStrategy(
address staker,
IStrategy strategy,
IERC20 token,
uint256 amount
) internal onlyStrategiesWhitelistedForDeposit(strategy) returns (uint256 depositedShares) {
) internal onlyStrategiesWhitelistedForDeposit(strategy) returns (uint256 shares) {
// transfer tokens from the sender to the strategy
token.safeTransferFrom(msg.sender, address(strategy), amount);

// deposit the assets into the specified strategy and get the equivalent amount of shares in that strategy
depositedShares = strategy.deposit(token, amount);
shares = strategy.deposit(token, amount);

// add the returned shares to the staker's existing shares for this strategy
_addDepositedShares(staker, token, strategy, depositedShares);
_addShares(staker, token, strategy, shares);

return depositedShares;
return shares;
}

/**
* @notice Decreases the shares that `staker` holds in `strategy` by `depositedSharesToRemove`.
* @notice Decreases the shares that `staker` holds in `strategy` by `depositSharesToRemove`.
* @param staker The address to decrement shares from
* @param strategy The strategy for which the `staker`'s shares are being decremented
* @param depositedSharesToRemove The amount of shares to decrement
* @param depositSharesToRemove The amount of deposit shares to decrement
* @dev If the amount of shares represents all of the staker`s shares in said strategy,
* then the strategy is removed from stakerStrategyList[staker] and 'true' is returned. Otherwise 'false' is returned.
*/
function _removeDepositedShares(address staker, IStrategy strategy, uint256 depositedSharesToRemove) internal returns (bool) {
function _removeDepositShares(address staker, IStrategy strategy, uint256 depositSharesToRemove) internal returns (bool) {
// sanity checks on inputs
require(depositedSharesToRemove != 0, SharesAmountZero());
require(depositSharesToRemove != 0, SharesAmountZero());

//check that the user has sufficient shares
uint256 userDepositedShares = stakerDepositShares[staker][strategy];
uint256 userDepositShares = stakerDepositShares[staker][strategy];

require(depositedSharesToRemove <= userDepositedShares, SharesAmountTooHigh());
require(depositSharesToRemove <= userDepositShares, SharesAmountTooHigh());

userDepositedShares = userDepositedShares - depositedSharesToRemove;
userDepositShares = userDepositShares - depositSharesToRemove;

// subtract the shares from the staker's existing shares for this strategy
stakerDepositShares[staker][strategy] = userDepositedShares;
stakerDepositShares[staker][strategy] = userDepositShares;

// if no existing shares, remove the strategy from the staker's dynamic array of strategies
if (userDepositedShares == 0) {
if (userDepositShares == 0) {
_removeStrategyFromStakerStrategyList(staker, strategy);

// return true in the event that the strategy was removed from stakerStrategyList[staker]
Expand Down
13 changes: 5 additions & 8 deletions src/contracts/interfaces/IDelegationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ interface IDelegationManager is ISignatureUtils {
* @param strategy The strategy in which to increase the delegated shares.
* @param existingDepositShares The number of deposit shares the staker already has in the strategy. This is the shares amount stored in the
* StrategyManager/EigenPodManager for the staker's shares.
* @param addedDepositShares The number of deposit shares added to the staker's shares in the strategy
* @param addedShares The number of shares added to the staker's shares in the strategy
*
* @dev *If the staker is actively delegated*, then increases the `staker`'s delegated delegatedShares in `strategy`.
* Otherwise does nothing.
Expand All @@ -362,7 +362,7 @@ interface IDelegationManager is ISignatureUtils {
address staker,
IStrategy strategy,
uint256 existingDepositShares,
uint256 addedDepositShares
uint256 addedShares
) external;

/**
Expand All @@ -385,14 +385,11 @@ interface IDelegationManager is ISignatureUtils {
* @notice Decreases the operators shares in storage after a slash
* @param operator The operator to decrease shares for
* @param strategy The strategy to decrease shares for
* @param newMagnitude The new magnitude to decrease shares by
* @param previousMagnitude The magnitude before the slash
* @param newMagnitude The magnitude after the slash
* @dev Callable only by the AllocationManager
*/
function updateOperatorShares(
address operator,
IStrategy strategy,
uint64 newMagnitude
) external;
function decreaseOperatorShares(address operator, IStrategy strategy, uint64 previousMagnitude, uint64 newMagnitude) external;

/**
* @notice returns the address of the operator that `staker` is delegated to.
Expand Down
Loading

0 comments on commit 8f0e116

Please sign in to comment.