Skip to content

Commit

Permalink
update epm and decrease interaction
Browse files Browse the repository at this point in the history
  • Loading branch information
gpsanant committed Sep 13, 2024
1 parent 527b6f9 commit 95512d0
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 128 deletions.
61 changes: 34 additions & 27 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 @@ -411,35 +416,42 @@ contract DelegationManager is
}

/**
* @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 scaling factor 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 removedShares 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 magnitudes.
* @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,
uint256 removedShares
) external onlyStrategyManagerOrEigenPodManager {
function decreaseBeaconChainScalingFactor(
address staker,
uint256 shares,
uint256 proportionPodBalanceDecrease
) external onlyEigenPodManager {
uint256 scaledSharesBefore =
shares
* beaconChainScalingFactors[staker] / SlashingConstants.PRECISION_FACTOR
* depositScalingFactors[staker][beaconChainETHStrategy] / SlashingConstants.PRECISION_FACTOR;

beaconChainScalingFactors[staker] = beaconChainScalingFactors[staker] * (SlashingConstants.PRECISION_FACTOR - proportionPodBalanceDecrease) / SlashingConstants.PRECISION_FACTOR;

uint256 scaledSharesAfter =
shares
* beaconChainScalingFactors[staker] / SlashingConstants.PRECISION_FACTOR
* depositScalingFactors[staker][beaconChainETHStrategy] / SlashingConstants.PRECISION_FACTOR;

// if the staker is delegated to an operator
if (isDelegated(staker)) {
address operator = delegatedTo[staker];

uint64 totalMagnitude = allocationManager.getTotalMagnitude(operator, strategy);

// subtract strategy shares from delegated scaled shares
_decreaseOperatorScaledShares({
operator: operator,
staker: staker,
strategy: strategy,
shares: removedShares,
totalMagnitude: totalMagnitude
strategy: beaconChainETHStrategy,
scaledShares: scaledSharesBefore - scaledSharesAfter
});
}
}
Expand Down Expand Up @@ -684,9 +696,9 @@ contract DelegationManager is
* Update shares amount depending upon the returned value.
* The return value will be lower than the input value in the case where the staker has an existing share deficit
*/
(shares, existingShares) = eigenPodManager.addShares({podOwner: staker, shares: shares});
eigenPodManager.addShares({podOwner: staker, shares: shares});
} else {
existingShares = strategyManager.addShares(msg.sender, tokens[i], withdrawal.strategies[i], shares);
strategyManager.addShares(msg.sender, tokens[i], withdrawal.strategies[i], shares);
}
}
}
Expand Down Expand Up @@ -719,18 +731,14 @@ contract DelegationManager is
* @param operator The operator to decrease the delegated scaled shares for
* @param staker The staker to decrease the delegated scaled shares for
* @param strategy The strategy to decrease the delegated scaled shares for
* @param shares The shares removed from the staker in the StrategyManager/EigenPodManager
* @param totalMagnitude The current total magnitude of the operator for the strategy
* @param scaledShares The scaled shares removed from the staker in the StrategyManager/EigenPodManager
*/
function _decreaseOperatorScaledShares(
address operator,
address staker,
IStrategy strategy,
uint256 shares,
uint64 totalMagnitude
uint256 scaledShares
) internal {
// based on total magnitude, decrement operator's scaled shares
uint256 scaledShares = _scaleShares(shares, totalMagnitude);
operatorScaledShares[operator][strategy] -= scaledShares;
// TODO: What to do about event wrt scaling?
emit OperatorSharesDecreased(operator, staker, strategy, scaledShares);
Expand Down Expand Up @@ -789,8 +797,7 @@ contract DelegationManager is
operator: operator,
staker: staker,
strategy: strategies[i],
shares: sharesToWithdraw[i],
totalMagnitude: totalMagnitudes[i]
scaledShares: _scaleShares(sharesToWithdraw[i], totalMagnitudes[i])
});
}

Expand Down
16 changes: 8 additions & 8 deletions src/contracts/interfaces/IDelegationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,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 @@ -356,18 +358,16 @@ 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 scaling factor 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 removedShares 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, uint256 removedShares) external;
function decreaseBeaconChainScalingFactor(address staker, uint256 shares, uint256 proportionPodBalanceDecrease) external;

/**
* @notice returns the address of the operator that `staker` is delegated to.
Expand Down
12 changes: 7 additions & 5 deletions src/contracts/interfaces/IEigenPodManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,15 @@ interface IEigenPodManager is 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 PRECISION_FACTOR) 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,
uint256 proportionPodBalanceDecrease
) external;

/// @notice Returns the address of the `podOwner`'s EigenPod if it has been deployed.
function ownerToPod(
Expand Down Expand Up @@ -132,15 +137,12 @@ interface IEigenPodManager is IPausable {
/**
* @notice Increases the `podOwner`'s shares by `shares`, paying off deficit if possible.
* Used by the DelegationManager to award a pod owner shares on exiting the withdrawal queue
* @dev Returns the number of shares added to `podOwnerShares[podOwner]` above zero, which will be less than the `shares` input
* in the event that the podOwner has an existing shares deficit (i.e. `podOwnerShares[podOwner]` starts below zero).
* Also returns existingPodShares prior to adding shares, this is returned as 0 if the existing podOwnerShares is negative
* @dev Reverts if `shares` is not a whole Gwei amount
*/
function addShares(
address podOwner,
uint256 shares
) external returns (uint256 increaseInDelegateableShares, uint256 existingPodShares);
) external;

/**
* @notice Used by the DelegationManager to complete a withdrawal, sending tokens to some destination address
Expand Down
4 changes: 2 additions & 2 deletions src/contracts/pods/EigenPod.sol
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ contract EigenPod is Initializable, ReentrancyGuardUpgradeable, EigenPodPausingC
}

// Update the EigenPodManager on this pod's new balance
eigenPodManager.recordBeaconChainETHBalanceUpdate(podOwner, int256(totalAmountToBeRestakedWei));
eigenPodManager.recordBeaconChainETHBalanceUpdate(podOwner, int256(totalAmountToBeRestakedWei), /* TODO */ 0);
}

/**
Expand Down Expand Up @@ -636,7 +636,7 @@ contract EigenPod is Initializable, ReentrancyGuardUpgradeable, EigenPodPausingC
delete _currentCheckpoint;

// Update pod owner's shares
eigenPodManager.recordBeaconChainETHBalanceUpdate(podOwner, totalShareDeltaWei);
eigenPodManager.recordBeaconChainETHBalanceUpdate(podOwner, totalShareDeltaWei, /* TODO */ 0);
emit CheckpointFinalized(lastCheckpointTimestamp, totalShareDeltaWei);
} else {
_currentCheckpoint = checkpoint;
Expand Down
110 changes: 33 additions & 77 deletions src/contracts/pods/EigenPodManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -97,46 +97,26 @@ contract EigenPodManager is
* 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 PRECISION_FACTOR) 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
int256 sharesDelta,
uint256 proportionPodBalanceDecrease
) external onlyEigenPod(podOwner) nonReentrant {
require(podOwner != address(0), InputAddressZero());
require(sharesDelta % int256(GWEI_TO_WEI) == 0, SharesNotMultipleOfGwei());
int256 currentPodOwnerShares = podOwnerShares[podOwner];
int256 updatedPodOwnerShares = currentPodOwnerShares + sharesDelta;
podOwnerShares[podOwner] = updatedPodOwnerShares;

// inform the DelegationManager of the change in delegateable shares
int256 changeInDelegatableShares = _calculateChangeInDelegatableShares({
sharesBefore: currentPodOwnerShares,
sharesAfter: updatedPodOwnerShares
});
// skip making a call to the DelegationManager if there is no change in delegateable shares
// or if the currentPodShares < 0 and updatedPodShares is still < 0. Means no update required
// in delegated shares
if (changeInDelegatableShares != 0) {
if (changeInDelegatableShares < 0) {
delegationManager.decreaseDelegatedShares({
staker: podOwner,
strategy: beaconChainETHStrategy,
removedShares: uint256(-changeInDelegatableShares)
});
} else {
delegationManager.increaseDelegatedShares({
staker: podOwner,
strategy: beaconChainETHStrategy,
// existing shares from standpoint of the DelegationManager
existingShares: currentPodOwnerShares < 0 ? 0 : uint256(currentPodOwnerShares),
addedShares: uint256(changeInDelegatableShares)
});
}
if (sharesDelta > 0) {
_addShares(podOwner, uint256(sharesDelta));
} else if (sharesDelta < 0 && podOwnerShares[podOwner] > 0) {
delegationManager.decreaseBeaconChainScalingFactor(
podOwner,
uint256(podOwnerShares[podOwner]),
proportionPodBalanceDecrease
);
}
emit PodSharesUpdated(podOwner, sharesDelta);
emit NewTotalShares(podOwner, updatedPodOwnerShares);
}

/**
Expand Down Expand Up @@ -169,26 +149,8 @@ contract EigenPodManager is
function addShares(
address podOwner,
uint256 shares
) external onlyDelegationManager returns (uint256 increaseInDelegateableShares, uint256 existingPodShares) {
require(podOwner != address(0), InputAddressZero());
require(int256(shares) >= 0, SharesNegative());
require(shares % GWEI_TO_WEI == 0, SharesNotMultipleOfGwei());
int256 currentPodOwnerShares = podOwnerShares[podOwner];
int256 updatedPodOwnerShares = currentPodOwnerShares + int256(shares);
podOwnerShares[podOwner] = updatedPodOwnerShares;

emit PodSharesUpdated(podOwner, int256(shares));
emit NewTotalShares(podOwner, updatedPodOwnerShares);

increaseInDelegateableShares = uint256(
_calculateChangeInDelegatableShares({
sharesBefore: currentPodOwnerShares,
sharesAfter: updatedPodOwnerShares
})
);
existingPodShares = currentPodOwnerShares < 0 ? 0 : uint256(currentPodOwnerShares);

return (increaseInDelegateableShares, existingPodShares);
) external onlyDelegationManager {
_addShares(podOwner, shares);
}

/**
Expand Down Expand Up @@ -252,32 +214,26 @@ contract EigenPodManager is
return pod;
}

/**
* @notice Calculates the change in a pod owner's delegateable shares as a result of their beacon chain ETH shares changing
* from `sharesBefore` to `sharesAfter`. The key concept here is that negative/"deficit" shares are not delegateable.
*/
function _calculateChangeInDelegatableShares(
int256 sharesBefore,
int256 sharesAfter
) internal pure returns (int256) {
if (sharesBefore <= 0) {
if (sharesAfter <= 0) {
// if the shares started negative and stayed negative, then there cannot have been an increase in delegateable shares
return 0;
} else {
// if the shares started negative and became positive, then the increase in delegateable shares is the ending share amount
return sharesAfter;
}
} else {
if (sharesAfter <= 0) {
// if the shares started positive and became negative, then the decrease in delegateable shares is the starting share amount
return (-sharesBefore);
} else {
// if the shares started positive and stayed positive, then the change in delegateable shares
// is the difference between starting and ending amounts
return (sharesAfter - sharesBefore);
}
}
function _addShares(
address podOwner,
uint256 shares
) internal {
require(podOwner != address(0), InputAddressZero());
require(int256(shares) >= 0, SharesNegative());
int256 currentPodOwnerShares = podOwnerShares[podOwner];
int256 updatedPodOwnerShares = currentPodOwnerShares + int256(shares);
podOwnerShares[podOwner] = updatedPodOwnerShares;

emit PodSharesUpdated(podOwner, int256(shares));
emit NewTotalShares(podOwner, updatedPodOwnerShares);

delegationManager.increaseDelegatedShares({
staker: podOwner,
strategy: beaconChainETHStrategy,
// existing shares from standpoint of the DelegationManager
existingShares: currentPodOwnerShares < 0 ? 0 : uint256(currentPodOwnerShares),
addedShares: uint256(shares)
});
}

// VIEW FUNCTIONS
Expand Down
2 changes: 1 addition & 1 deletion src/test/harnesses/EigenPodManagerWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ contract EigenPodManagerWrapper is EigenPodManager {
) EigenPodManager(_ethPOS, _eigenPodBeacon, _strategyManager, _slasher, _delegationManager) {}

function calculateChangeInDelegatableShares(int256 sharesBefore, int256 sharesAfter) external pure returns (int256) {
return _calculateChangeInDelegatableShares(sharesBefore, sharesAfter);
// return _calculateChangeInDelegatableShares(sharesBefore, sharesAfter);
}

function setPodAddress(address owner, IEigenPod pod) external {
Expand Down
6 changes: 5 additions & 1 deletion src/test/mocks/DelegationManagerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ contract DelegationManagerMock is IDelegationManager, Test {
uint256 addedShares
) external {}

function decreaseDelegatedShares(address staker, IStrategy strategy, uint256 shares) external {}
function decreaseBeaconChainScalingFactor(
address staker,
uint256 shares,
uint256 proportionPodBalanceDecrease
) external {}

function operatorDetails(address operator) external pure returns (OperatorDetails memory) {
OperatorDetails memory returnValue = OperatorDetails({
Expand Down
10 changes: 8 additions & 2 deletions src/test/mocks/EigenPodManagerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ contract EigenPodManagerMock is IEigenPodManager, Test, Pausable {

function stake(bytes calldata /*pubkey*/, bytes calldata /*signature*/, bytes32 /*depositDataRoot*/) external payable {}

function recordBeaconChainETHBalanceUpdate(address /*podOwner*/, int256 /*sharesDelta*/) external pure {}
function recordBeaconChainETHBalanceUpdate(
address podOwner,
int256 sharesDelta,
uint256 proportionPodBalanceDecrease
) external {

}

function ownerToPod(address /*podOwner*/) external pure returns(IEigenPod) {
return IEigenPod(address(0));
Expand Down Expand Up @@ -53,7 +59,7 @@ contract EigenPodManagerMock is IEigenPodManager, Test, Pausable {
podShares[podOwner] = shares;
}

function addShares(address /*podOwner*/, uint256 shares) external pure returns (uint256, uint256) {
function addShares(address /*podOwner*/, uint256 shares) external pure {
// this is the "increase in delegateable tokens"
// return (shares);
}
Expand Down
Loading

0 comments on commit 95512d0

Please sign in to comment.