Skip to content

Commit

Permalink
change struct
Browse files Browse the repository at this point in the history
  • Loading branch information
gpsanant committed Sep 21, 2024
1 parent 3d1d44b commit ad11f4d
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 49 deletions.
52 changes: 29 additions & 23 deletions src/contracts/core/DelegationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -288,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]].set(WAD);
stakerScalingFactors[staker][strategies[i]].depositScalingFactor = WAD;
}
}

Expand Down Expand Up @@ -420,20 +420,23 @@ contract DelegationManager is
uint256 existingPrincipalShares,
uint64 proportionPodBalanceDecrease
) external onlyEigenPodManager {
PrincipalShares existingPrincipalShares = PrincipalShares.wrap(existingPrincipalShares);

// todo: set beaconChainScalingFactors
DelegatedShares delegatedSharesBefore = PrincipalShares.wrap(existingPrincipalShares).toDelegatedShares(
depositScalingFactors[staker][beaconChainETHStrategy],
beaconChainScalingFactors[staker][beaconChainETHStrategy]
DelegatedShares delegatedSharesBefore = existingPrincipalShares.toDelegatedShares(
stakerScalingFactors[staker][beaconChainETHStrategy]
);

// TODO: is this subtraction problematic rounding wise?
// decrease the staker's beaconChainScalingFactor proportionally
beaconChainScalingFactors[staker][beaconChainETHStrategy].set(
beaconChainScalingFactors[staker][beaconChainETHStrategy].get() * (WAD - proportionPodBalanceDecrease) / WAD
);

DelegatedShares delegatedSharesAfter = PrincipalShares.wrap(existingPrincipalShares).toDelegatedShares(
depositScalingFactors[staker][beaconChainETHStrategy],
beaconChainScalingFactors[staker][beaconChainETHStrategy]
// forgefmt: disable-next-item
stakerScalingFactors[staker][beaconChainETHStrategy].beaconChainScalingFactor =
stakerScalingFactors[staker][beaconChainETHStrategy].getBeaconChainScalingFactor()
* (WAD - proportionPodBalanceDecrease) / WAD;
stakerScalingFactors[staker][beaconChainETHStrategy].isBeaconChainScalingFactorSet = true;

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

// if the staker is delegated to an operators
Expand All @@ -445,7 +448,8 @@ contract DelegationManager is
operator: operator,
staker: staker,
strategy: beaconChainETHStrategy,
delegatedShares: DelegatedShares.unwrap(delegatedSharesBefore)
delegatedShares:
DelegatedShares.unwrap(delegatedSharesBefore)
- DelegatedShares.unwrap(delegatedSharesAfter)
});
}
Expand Down Expand Up @@ -673,9 +677,7 @@ contract DelegationManager is
// TODO: handle beaconchain slashing
delegatedSharesToWithdraw[i] = Shares.wrap(sharesToWithdraw[i]).toDelegatedShares(totalMagnitudes[i]);
uint256 principalSharesToWithdraw = PrincipalShares.unwrap(
delegatedSharesToWithdraw[i].toPrincipalShares(
depositScalingFactors[staker][strategies[i]], beaconChainScalingFactors[staker][strategies[i]]
)
delegatedSharesToWithdraw[i].toPrincipalShares(stakerScalingFactors[staker][strategies[i]])
);

// TODO: maybe have a getter to get shares for all strategies, like getDelegatableShares
Expand Down Expand Up @@ -762,7 +764,7 @@ contract DelegationManager is
uint256 addedShares
) internal returns (uint256) {
// TODO: overflow analysis
uint128 newDepositScalingFactor;
uint256 newDepositScalingFactor;

if (existingPrincipalShares == 0) {
// existing shares are 0, meaning no existing delegated shares. In this case, the new depositScalingFactor
Expand All @@ -786,16 +788,19 @@ contract DelegationManager is
// we can solve for
//
uint256 existingShares = Shares.unwrap(
PrincipalShares.wrap(existingPrincipalShares).toDelegatedShares(depositScalingFactors[staker][strategy]).toShares(
PrincipalShares.wrap(existingPrincipalShares).toDelegatedShares(stakerScalingFactors[staker][strategy]).toShares(
totalMagnitude
)
);
newDepositScalingFactor = (existingShares + addedShares) * WAD
/ (existingPrincipalShares + addedShares) * WAD / totalMagnitude;
// forgefmt: disable-next-item
newDepositScalingFactor = (existingShares + addedShares)
* WAD / (existingPrincipalShares + addedShares)
* WAD / stakerScalingFactors[staker][strategy].getBeaconChainScalingFactor()
* WAD / totalMagnitude;
}

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

function _getShareManager(
Expand Down Expand Up @@ -899,10 +904,11 @@ contract DelegationManager is
// in the StrategyManager/EigenPodManager because they could have been slashed
if (operator != address(0)) {
uint64 totalMagnitude = allocationManager.getTotalMagnitude(operator, strategies[i]);
// forgefmt: disable-next-item
shares[i] = Shares.unwrap(
PrincipalShares.wrap(shares[i]).toDelegatedShares(
depositScalingFactors[staker][strategies[i]], beaconChainScalingFactors[staker][strategies[i]]
).toShares(totalMagnitude)
PrincipalShares.wrap(shares[i])
.toDelegatedShares(stakerScalingFactors[staker][strategies[i]])
.toShares(totalMagnitude)
);
}
}
Expand Down
15 changes: 7 additions & 8 deletions src/contracts/core/DelegationManagerStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,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 of a delegated staker.
mapping(address => mapping(IStrategy => Uint128DefaultWad)) public depositScalingFactors;

/// @notice Mapping: staker => strategy => their beacon chain scaling factor used to calculate the staker's withdrawable shares in the strategy.
/// This is updated upon each ending checkpoints that include beacon chain slashing.
/// Note that we don't need the Stratgy mapping here, since this will only be non zero for beaconChainETHStrategy, but it's nicer syntactically to keep it.
mapping(address => mapping(IStrategy => Uint128DefaultWad)) public beaconChainScalingFactors;
/// @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
43 changes: 26 additions & 17 deletions src/contracts/libraries/SlashingLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,18 @@ type DelegatedShares is uint256;

type PrincipalShares is uint256;

struct Uint128DefaultWad {
uint128 inner;
bool isSet;
struct StakerScalingFactors {
uint256 depositScalingFactor;

// we need to know if the beaconChainScalingFactor is set because it can be set to 0 through 100% slashing
bool isBeaconChainScalingFactorSet;
uint64 beaconChainScalingFactor;
}

using SlashingLib for Shares global;
using SlashingLib for DelegatedShares global;
using SlashingLib for PrincipalShares global;
using SlashingLib for Uint128DefaultWad global;
using SlashingLib for StakerScalingFactors global;

// TODO: validate order of operations everywhere
library SlashingLib {
Expand All @@ -65,20 +68,27 @@ library SlashingLib {
/// @dev beaconChainScalingFactor = 0 -> WAD for all non beaconChainETH strategies
function toPrincipalShares(
DelegatedShares delegatedShares,
Uint128DefaultWad storage depositScalingFactor,
Uint128DefaultWad storage beaconChainScalingFactor
StakerScalingFactors storage ssf
) internal view returns (PrincipalShares) {
return PrincipalShares.wrap(DelegatedShares.unwrap(delegatedShares).divWad(depositScalingFactor.get()).divWad(beaconChainScalingFactor.get()));
return PrincipalShares.wrap(
DelegatedShares.unwrap(delegatedShares)
.divWad(ssf.getDepositScalingFactor())
.divWad(ssf.getBeaconChainScalingFactor())
);
}

/// @dev beaconChainScalingFactor = 0 -> WAD for all non beaconChainETH strategies
function toDelegatedShares(
PrincipalShares principalShares,
Uint128DefaultWad storage depositScalingFactor,
Uint128DefaultWad storage beaconChainScalingFactor
StakerScalingFactors storage ssf
) internal view returns (DelegatedShares) {
return DelegatedShares.wrap(PrincipalShares.unwrap(principalShares).mulWad(depositScalingFactor.get()).mulWad(beaconChainScalingFactor.get()));
return DelegatedShares.wrap(
PrincipalShares.unwrap(principalShares)
.mulWad(ssf.getDepositScalingFactor())
.mulWad(ssf.getBeaconChainScalingFactor())
);
}


function toShares(DelegatedShares delegatedShares, uint256 magnitude) internal view returns (Shares) {
return Shares.wrap(DelegatedShares.unwrap(delegatedShares).mulWad(magnitude));
Expand All @@ -97,13 +107,12 @@ library SlashingLib {
function divWad(uint256 a, uint256 b) internal pure returns (uint256) {
return a.mulDiv(WAD, b);
}

function get(Uint128DefaultWad storage a) internal view returns (uint128) {
return a.inner == 0 && !a.isSet ? WAD : a.inner;
}

function set(Uint128DefaultWad storage a, uint128 newVal) internal {
a.isSet = true;
a.inner = newVal;
function getDepositScalingFactor(StakerScalingFactors storage ssf) internal view returns (uint256) {
return ssf.depositScalingFactor == 0 ? WAD : ssf.depositScalingFactor;
}

function getBeaconChainScalingFactor(StakerScalingFactors storage ssf) internal view returns (uint64) {
return !ssf.isBeaconChainScalingFactorSet && ssf.beaconChainScalingFactor == 0 ? WAD : ssf.beaconChainScalingFactor;
}
}
2 changes: 1 addition & 1 deletion src/contracts/pods/EigenPodStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ abstract contract EigenPodStorage is IEigenPod {
mapping(uint64 => uint64) public checkpointBalanceExitedGwei;

/// @notice The current checkpoint, if there is one active
Checkpoint internal _currentCheckpoint;
Checkpoint internal _currentCheckpoint; // TODO: this storage is fucked need split structs

/// @notice An address with permissions to call `startCheckpoint` and `verifyWithdrawalCredentials`, set
/// by the podOwner. This role exists to allow a podOwner to designate a hot wallet that can call
Expand Down

0 comments on commit ad11f4d

Please sign in to comment.