Skip to content

Commit 81fef63

Browse files
8sunyuanwadealexc
andauthored
fix: reentrant guards (#1107)
**Motivation:** Concerns about reentrancy in the DelegationManager and interactions of completed withdrawals which can call untrusted ERC20 transfers **Modifications:** Added reentrant guards across external functions **Result:** Preventing cross-function reentrancy in the DelegationManager --------- Co-authored-by: wadealexc <[email protected]>
1 parent 067010c commit 81fef63

File tree

3 files changed

+27
-21
lines changed

3 files changed

+27
-21
lines changed

src/contracts/core/DelegationManager.sol

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ contract DelegationManager is
9696
address initDelegationApprover,
9797
uint32 allocationDelay,
9898
string calldata metadataURI
99-
) external {
99+
) external nonReentrant {
100100
require(!isDelegated(msg.sender), ActivelyDelegated());
101101

102102
allocationManager.setAllocationDelay(msg.sender, allocationDelay);
@@ -110,7 +110,10 @@ contract DelegationManager is
110110
}
111111

112112
/// @inheritdoc IDelegationManager
113-
function modifyOperatorDetails(address operator, address newDelegationApprover) external checkCanCall(operator) {
113+
function modifyOperatorDetails(
114+
address operator,
115+
address newDelegationApprover
116+
) external checkCanCall(operator) nonReentrant {
114117
require(isOperator(operator), OperatorNotRegistered());
115118
_setDelegationApprover(operator, newDelegationApprover);
116119
}
@@ -126,7 +129,7 @@ contract DelegationManager is
126129
address operator,
127130
SignatureWithExpiry memory approverSignatureAndExpiry,
128131
bytes32 approverSalt
129-
) public {
132+
) public nonReentrant {
130133
require(!isDelegated(msg.sender), ActivelyDelegated());
131134
require(isOperator(operator), OperatorNotRegistered());
132135

@@ -145,7 +148,7 @@ contract DelegationManager is
145148
/// @inheritdoc IDelegationManager
146149
function undelegate(
147150
address staker
148-
) public returns (bytes32[] memory withdrawalRoots) {
151+
) public nonReentrant returns (bytes32[] memory withdrawalRoots) {
149152
// Check that the `staker` can undelegate
150153
require(isDelegated(staker), NotActivelyDelegated());
151154
require(!isOperator(staker), OperatorsCannotUndelegate());
@@ -176,7 +179,7 @@ contract DelegationManager is
176179
/// @inheritdoc IDelegationManager
177180
function queueWithdrawals(
178181
QueuedWithdrawalParams[] calldata params
179-
) external onlyWhenNotPaused(PAUSED_ENTER_WITHDRAWAL_QUEUE) returns (bytes32[] memory) {
182+
) external onlyWhenNotPaused(PAUSED_ENTER_WITHDRAWAL_QUEUE) nonReentrant returns (bytes32[] memory) {
180183
bytes32[] memory withdrawalRoots = new bytes32[](params.length);
181184
address operator = delegatedTo[msg.sender];
182185

@@ -228,7 +231,7 @@ contract DelegationManager is
228231
IStrategy strategy,
229232
uint256 prevDepositShares,
230233
uint256 addedShares
231-
) external onlyStrategyManagerOrEigenPodManager {
234+
) external onlyStrategyManagerOrEigenPodManager nonReentrant {
232235
/// Note: Unlike `decreaseDelegatedShares`, we don't return early if the staker has no operator.
233236
/// This is because `_increaseDelegation` updates the staker's deposit scaling factor, which we
234237
/// need to do even if not delegated.
@@ -252,7 +255,7 @@ contract DelegationManager is
252255
address staker,
253256
uint256 curDepositShares,
254257
uint64 beaconChainSlashingFactorDecrease
255-
) external onlyEigenPodManager {
258+
) external onlyEigenPodManager nonReentrant {
256259
if (!isDelegated(staker)) {
257260
return;
258261
}
@@ -282,7 +285,7 @@ contract DelegationManager is
282285
IStrategy strategy,
283286
uint64 prevMaxMagnitude,
284287
uint64 newMaxMagnitude
285-
) external onlyAllocationManager {
288+
) external onlyAllocationManager nonReentrant {
286289
/// forgefmt: disable-next-item
287290
uint256 operatorSharesSlashed = SlashingLib.calcSlashedAmount({
288291
operatorShares: operatorShares[operator][strategy],

src/contracts/core/StrategyManager.sol

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ contract StrategyManager is
117117
address staker,
118118
IStrategy strategy,
119119
uint256 depositSharesToRemove
120-
) external onlyDelegationManager returns (uint256) {
120+
) external onlyDelegationManager nonReentrant returns (uint256) {
121121
(, uint256 sharesAfter) = _removeDepositShares(staker, strategy, depositSharesToRemove);
122122
return sharesAfter;
123123
}
@@ -127,7 +127,7 @@ contract StrategyManager is
127127
address staker,
128128
IStrategy strategy,
129129
uint256 shares
130-
) external onlyDelegationManager returns (uint256, uint256) {
130+
) external onlyDelegationManager nonReentrant returns (uint256, uint256) {
131131
return _addShares(staker, strategy, shares);
132132
}
133133

@@ -137,12 +137,15 @@ contract StrategyManager is
137137
IStrategy strategy,
138138
IERC20 token,
139139
uint256 shares
140-
) external onlyDelegationManager {
140+
) external onlyDelegationManager nonReentrant {
141141
strategy.withdraw(staker, token, shares);
142142
}
143143

144144
/// @inheritdoc IShareManager
145-
function increaseBurnableShares(IStrategy strategy, uint256 addedSharesToBurn) external onlyDelegationManager {
145+
function increaseBurnableShares(
146+
IStrategy strategy,
147+
uint256 addedSharesToBurn
148+
) external onlyDelegationManager nonReentrant {
146149
(, uint256 currentShares) = EnumerableMap.tryGet(burnableShares, address(strategy));
147150
EnumerableMap.set(burnableShares, address(strategy), currentShares + addedSharesToBurn);
148151
emit BurnableSharesIncreased(strategy, addedSharesToBurn);
@@ -162,14 +165,14 @@ contract StrategyManager is
162165
/// @inheritdoc IStrategyManager
163166
function setStrategyWhitelister(
164167
address newStrategyWhitelister
165-
) external onlyOwner {
168+
) external onlyOwner nonReentrant {
166169
_setStrategyWhitelister(newStrategyWhitelister);
167170
}
168171

169172
/// @inheritdoc IStrategyManager
170173
function addStrategiesToDepositWhitelist(
171174
IStrategy[] calldata strategiesToWhitelist
172-
) external onlyStrategyWhitelister {
175+
) external onlyStrategyWhitelister nonReentrant {
173176
uint256 strategiesToWhitelistLength = strategiesToWhitelist.length;
174177
for (uint256 i = 0; i < strategiesToWhitelistLength; ++i) {
175178
// change storage and emit event only if strategy is not already in whitelist
@@ -183,7 +186,7 @@ contract StrategyManager is
183186
/// @inheritdoc IStrategyManager
184187
function removeStrategiesFromDepositWhitelist(
185188
IStrategy[] calldata strategiesToRemoveFromWhitelist
186-
) external onlyStrategyWhitelister {
189+
) external onlyStrategyWhitelister nonReentrant {
187190
uint256 strategiesToRemoveFromWhitelistLength = strategiesToRemoveFromWhitelist.length;
188191
for (uint256 i = 0; i < strategiesToRemoveFromWhitelistLength; ++i) {
189192
// change storage and emit event only if strategy is already in whitelist

src/contracts/pods/EigenPodManager.sol

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ contract EigenPodManager is
6666
}
6767

6868
/// @inheritdoc IEigenPodManager
69-
function createPod() external onlyWhenNotPaused(PAUSED_NEW_EIGENPODS) returns (address) {
69+
function createPod() external onlyWhenNotPaused(PAUSED_NEW_EIGENPODS) nonReentrant returns (address) {
7070
require(!hasPod(msg.sender), EigenPodAlreadyExists());
7171
// deploy a pod if the sender doesn't have one already
7272
IEigenPod pod = _deployPod();
@@ -79,7 +79,7 @@ contract EigenPodManager is
7979
bytes calldata pubkey,
8080
bytes calldata signature,
8181
bytes32 depositDataRoot
82-
) external payable onlyWhenNotPaused(PAUSED_NEW_EIGENPODS) {
82+
) external payable onlyWhenNotPaused(PAUSED_NEW_EIGENPODS) nonReentrant {
8383
IEigenPod pod = ownerToPod[msg.sender];
8484
if (address(pod) == address(0)) {
8585
//deploy a pod if the sender doesn't have one already
@@ -148,7 +148,7 @@ contract EigenPodManager is
148148
address staker,
149149
IStrategy strategy,
150150
uint256 depositSharesToRemove
151-
) external onlyDelegationManager returns (uint256) {
151+
) external onlyDelegationManager nonReentrant returns (uint256) {
152152
require(strategy == beaconChainETHStrategy, InvalidStrategy());
153153
int256 updatedShares = podOwnerDepositShares[staker] - int256(depositSharesToRemove);
154154
require(updatedShares >= 0, SharesNegative());
@@ -169,7 +169,7 @@ contract EigenPodManager is
169169
address staker,
170170
IStrategy strategy,
171171
uint256 shares
172-
) external onlyDelegationManager returns (uint256, uint256) {
172+
) external onlyDelegationManager nonReentrant returns (uint256, uint256) {
173173
require(strategy == beaconChainETHStrategy, InvalidStrategy());
174174
return _addShares(staker, shares);
175175
}
@@ -185,7 +185,7 @@ contract EigenPodManager is
185185
IStrategy strategy,
186186
IERC20,
187187
uint256 shares
188-
) external onlyDelegationManager {
188+
) external onlyDelegationManager nonReentrant {
189189
require(strategy == beaconChainETHStrategy, InvalidStrategy());
190190
require(staker != address(0), InputAddressZero());
191191
require(int256(shares) > 0, SharesNegative());
@@ -226,7 +226,7 @@ contract EigenPodManager is
226226
}
227227

228228
/// @inheritdoc IShareManager
229-
function increaseBurnableShares(IStrategy, uint256 addedSharesToBurn) external onlyDelegationManager {
229+
function increaseBurnableShares(IStrategy, uint256 addedSharesToBurn) external onlyDelegationManager nonReentrant {
230230
burnableETHShares += addedSharesToBurn;
231231
emit BurnableETHSharesIncreased(addedSharesToBurn);
232232
}

0 commit comments

Comments
 (0)