Skip to content

Commit

Permalink
squash
Browse files Browse the repository at this point in the history
  • Loading branch information
gpsanant committed Sep 25, 2024
1 parent c2b8c8f commit adb85e3
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 182 deletions.
93 changes: 55 additions & 38 deletions src/contracts/core/DelegationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ contract DelegationManager is
_;
}

modifier onlyEigenPodManager() {
require(msg.sender == address(eigenPodManager), OnlyEigenPodManager());
_;
}

Check notice

Code scanning / Slither

Incorrect modifier Low

Modifier DelegationManager.onlyEigenPodManager() does not always execute _; or revert

/**
*
* INITIALIZING FUNCTIONS
Expand Down Expand Up @@ -283,7 +288,7 @@ contract DelegationManager is

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

Expand Down Expand Up @@ -400,37 +405,45 @@ contract DelegationManager is
}
}

// IGNORE THIS FUNCTION
/**
* @notice Decreases a staker's delegated delegatedShares for a strategy.
* @param staker The address to increase the delegated scaled shares for their operator.
* @param strategy The strategy in which to decrease the delegated scaled shares.
* @param removedOwnedShares The number of shares to decremented for the strategy in the
* StrategyManager/EigenPodManager
* @notice Decreases a native restaker's delegated share balance in a strategy due to beacon chain slashing. This updates their beaconChainScalingFactor.
* Their operator's stakeShares are also updated (if they are delegated).
* @param staker The address to increase the delegated stakeShares for their operator.
* @param existingShares The number of shares the staker already has in the EPM. This does not change upon decreasing shares.
* @param proportionPodBalanceDecrease The proportion of the staker's shares to decrease. This is a fraction of the staker's shares in the strategy.
*
* @dev *If the staker is actively delegated*, then decreases the `staker`'s delegated delegatedShares in `strategy` by `scaledShares`. Otherwise does nothing.
* @dev Callable only by the StrategyManager or EigenPodManager.
* @dev *If the staker is actively delegated*, then decreases the `staker`'s delegated stakeShares in `strategy` by `proportionPodBalanceDecrease` proportion. Otherwise does nothing.
* @dev Callable only by the EigenPodManager.
*/
function decreaseDelegatedShares(
function decreaseBeaconChainScalingFactor(
address staker,
IStrategy strategy,
OwnedShares removedOwnedShares
) external onlyStrategyManagerOrEigenPodManager {
// if the staker is delegated to an operator
// if (isDelegated(staker)) {
// address operator = delegatedTo[staker];
Shares existingShares,
uint64 proportionPodBalanceDecrease
) external onlyEigenPodManager {
DelegatedShares delegatedSharesBefore = existingShares.toDelegatedShares(stakerScalingFactors[staker][beaconChainETHStrategy]);

// TODO: is this subtraction problematic rounding wise?
// decrease the staker's beaconChainScalingFactor proportionally
// forgefmt: disable-next-item
stakerScalingFactors[staker][beaconChainETHStrategy].beaconChainScalingFactor =
stakerScalingFactors[staker][beaconChainETHStrategy].getBeaconChainScalingFactor()
* (WAD - proportionPodBalanceDecrease) / WAD;
stakerScalingFactors[staker][beaconChainETHStrategy].isBeaconChainScalingFactorSet = true;

DelegatedShares delegatedSharesAfter = existingShares.toDelegatedShares(stakerScalingFactors[staker][beaconChainETHStrategy]);

// uint64 totalMagnitude = allocationManager.getTotalMagnitude(operator, strategy);
// if the staker is delegated to an operators
if (isDelegated(staker)) {
address operator = delegatedTo[staker];

// // subtract strategy shares from delegated scaled shares
// _decreaseOperatorScaledShares({
// operator: operator,
// staker: staker,
// strategy: strategy,
// shares: removedOwnedShares,
// totalMagnitude: totalMagnitude
// });
// }
// subtract strategy shares from delegated scaled shares
_decreaseDelegation({
operator: operator,
staker: staker,
strategy: beaconChainETHStrategy,
delegatedShares: delegatedSharesBefore.sub(delegatedSharesAfter)
});
}
}

/**
Expand Down Expand Up @@ -553,9 +566,11 @@ contract DelegationManager is

for (uint256 i = 0; i < withdrawal.strategies.length; i++) {
IShareManager shareManager = _getShareManager(withdrawal.strategies[i]);

// forgefmt: disable-next-line
OwnedShares ownedSharesToWithdraw = withdrawal.delegatedShares[i].toOwnedShares(totalMagnitudes[i]);
OwnedShares ownedSharesToWithdraw =
withdrawal.delegatedShares[i]
.scaleForCompleteWithdrawal(stakerScalingFactors[withdrawal.staker][withdrawal.strategies[i]])
.toOwnedShares(totalMagnitudes[i]);

if (receiveAsTokens) {
// Withdraws `shares` in `strategy` to `withdrawer`. If the shares are virtual beaconChainETH shares,
// then a call is ultimately forwarded to the `staker`s EigenPod; otherwise a call is ultimately forwarded
Expand Down Expand Up @@ -659,9 +674,8 @@ contract DelegationManager is
IShareManager shareManager = _getShareManager(strategies[i]);

// delegatedShares for staker to place into queueWithdrawal
delegatedSharesToWithdraw[i] = ownedSharesToWithdraw[i].toDelegatedShares(totalMagnitudes[i]);

Shares sharesToWithdraw = delegatedSharesToWithdraw[i].toShares(depositScalingFactors[staker][strategies[i]]);
DelegatedShares delegatedSharesToRemove = ownedSharesToWithdraw[i].toDelegatedShares(totalMagnitudes[i]);
Shares sharesToWithdraw = delegatedSharesToRemove.toShares(stakerScalingFactors[staker][strategies[i]]);
// TODO: maybe have a getter to get shares for all strategies, like getDelegatableShares
// check sharesToWithdraw is valid
// but for inputted strategies
Expand All @@ -675,9 +689,10 @@ contract DelegationManager is
operator: operator,
staker: staker,
strategy: strategies[i],
delegatedShares: delegatedSharesToWithdraw[i]
delegatedShares: delegatedSharesToRemove
});
}
delegatedSharesToWithdraw[i] = delegatedSharesToRemove.scaleForQueueWithdrawal(stakerScalingFactors[staker][strategies[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 @@ -733,6 +748,7 @@ 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.
Expand All @@ -758,25 +774,26 @@ contract DelegationManager is
//
// newShares
// = newPrincipalShares.toDelegatedShares(stakerScalingFactors[staker][strategy).toOwnedShares(totalMagnitude)
// = newPrincipalShares * newDepositScalingFactor / WAD * totalMagnitude / WAD
// = (existingPrincipalShares + addedShares) * newDepositScalingFactor / WAD * totalMagnitude / WAD
// = newPrincipalShares * newDepositScalingFactor / WAD * beaonChainScalingFactor / WAD * totalMagnitude / WAD
// = (existingPrincipalShares + addedShares) * newDepositScalingFactor / WAD * beaonChainScalingFactor / WAD * totalMagnitude / WAD
//
// we can solve for
//
OwnedShares existingOwnedShares =
existingShares
.toDelegatedShares(depositScalingFactors[staker][strategy])
.toDelegatedShares(stakerScalingFactors[staker][strategy])
.toOwnedShares(totalMagnitude);
newDepositScalingFactor =
existingOwnedShares
.add(addedOwnedShares)
.unwrap()
.divWad(existingShares.unwrap() + addedOwnedShares.unwrap())
.divWad(stakerScalingFactors[staker][strategy].getBeaconChainScalingFactor())
.divWad(totalMagnitude);
}

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

function _getShareManager(
Expand Down Expand Up @@ -885,7 +902,7 @@ contract DelegationManager is

// forgefmt: disable-next-item
ownedShares[i] = shares
.toDelegatedShares(depositScalingFactors[staker][strategies[i]])
.toDelegatedShares(stakerScalingFactors[staker][strategies[i]])
.toOwnedShares(totalMagnitude);
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/contracts/core/DelegationManagerStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,13 @@ abstract contract DelegationManagerStorage is IDelegationManager {
*/
mapping(IStrategy => uint256) private __deprecated_strategyWithdrawalDelayBlocks;

/// @notice Mapping: staker => strategy => scaling factor used to calculate the staker's shares in the strategy.
/// This is updated upon each deposit based on the staker's currently delegated operator's totalMagnitude.
mapping(address => mapping(IStrategy => uint256)) public depositScalingFactors;
/// @notice Mapping: staker => strategy =>
/// (
/// scaling factor used to calculate the staker's shares in the strategy,
/// 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 stakerScalingFactors;

constructor(
IStrategyManager _strategyManager,
Expand Down
20 changes: 12 additions & 8 deletions src/contracts/interfaces/IDelegationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ interface IDelegationManager is ISignatureUtils {
error OperatorNotRegistered();
/// @dev Thrown when caller is neither the StrategyManager or EigenPodManager contract.
error OnlyStrategyManagerOrEigenPodManager();
/// @dev Thrown when caller is not the EigenPodManager contract.
error OnlyEigenPodManager();
/// @dev Thrown when an operator attempts to undelegate.
error OperatorsCannotUndelegate();
/// @dev Thrown when an account is not actively delegated.
Expand Down Expand Up @@ -338,18 +340,20 @@ interface IDelegationManager is ISignatureUtils {
) external;

/**
* @notice Decreases a staker's delegated share balance in a strategy. Note that before removing from operator shares,
* the delegated shares are scaled according to the operator's total magnitude as part of slashing accounting. Unlike
* `increaseDelegatedShares`, the staker's depositScalingFactor is not updated here.
* @notice Decreases a native restaker's delegated share balance in a strategy due to beacon chain slashing. This updates their beaconChainScalingFactor.
* Their operator's scaled shares are also updated (if they are delegated).
* @param staker The address to increase the delegated scaled shares for their operator.
* @param strategy The strategy in which to decrease the delegated scaled shares.
* @param removedOwnedShares The number of shares to decremented for the strategy in the
* StrategyManager/EigenPodManager
* @param shares The number of shares of beaconChainETHStrategy the staker has, not including scaling factors or
* @param proportionPodBalanceDecrease The proportion of the staker's shares to decrease. This is a fraction of the staker's shares in the strategy.
*
* @dev *If the staker is actively delegated*, then decreases the `staker`'s delegated scaled shares in `strategy` by `scaledShares`. Otherwise does nothing.
* @dev Callable only by the StrategyManager or EigenPodManager.
* @dev Callable only by the EigenPodManager.
*/
function decreaseDelegatedShares(address staker, IStrategy strategy, OwnedShares removedOwnedShares) external;
function decreaseBeaconChainScalingFactor(
address staker,
Shares shares,
uint64 proportionPodBalanceDecrease
) external;

/**
* @notice returns the address of the operator that `staker` is delegated to.
Expand Down
2 changes: 2 additions & 0 deletions src/contracts/interfaces/IEigenPod.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ interface IEigenPod {
uint24 proofsRemaining;
uint64 podBalanceGwei;
int128 balanceDeltasGwei;
uint128 beaconChainBalanceBefore;
uint128 beaconChainBalanceAfter;
}

/**
Expand Down
10 changes: 9 additions & 1 deletion src/contracts/interfaces/IEigenPodManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ interface IEigenPodManager is IShareManager, IPausable {
error SharesNegative();
/// @dev Thrown when the strategy is not the beaconChainETH strategy.
error InvalidStrategy();
/// @dev Thrown when the pods shares are negative and a beacon chain balance update is attempted.
/// The podOwner should complete legacy withdrawal first.
error LegacyWithdrawalsNotCompleted();

/// @notice Emitted to notify the deployment of an EigenPod
event PodDeployed(address indexed eigenPod, address indexed podOwner);
Expand Down Expand Up @@ -72,10 +75,15 @@ interface IEigenPodManager is IShareManager, IPausable {
* to ensure that delegated shares are also tracked correctly
* @param podOwner is the pod owner whose balance is being updated.
* @param sharesDelta is the change in podOwner's beaconChainETHStrategy shares
* @param proportionPodBalanceDecrease is the proportion (of WAD) of the podOwner's balance that has changed
* @dev Callable only by the podOwner's EigenPod contract.
* @dev Reverts if `sharesDelta` is not a whole Gwei amount
*/
function recordBeaconChainETHBalanceUpdate(address podOwner, int256 sharesDelta) external;
function recordBeaconChainETHBalanceUpdate(
address podOwner,
int256 sharesDelta,
uint64 proportionPodBalanceDecrease
) external;

/// @notice Returns the address of the `podOwner`'s EigenPod if it has been deployed.
function ownerToPod(
Expand Down
Loading

0 comments on commit adb85e3

Please sign in to comment.