@@ -171,26 +171,35 @@ contract StrategyManager is
171171 EnumerableMap.AddressToUintMap storage operatorSetBurnableShares =
172172 _operatorSetBurnableShares[operatorSet.key ()][slashId];
173173
174- // Cache length to avoid sloads.
174+ // Iterate over burnable shares backwards. Iterating with an increasing index can cause
175+ // elements to be missed as the item to remove is swapped and popped with the last element.
175176 uint256 length = operatorSetBurnableShares.length ();
176177
177- // Iterate over all strategies that have burnable shares.
178- for (uint256 i = 0 ; i < length; ++ i) {
179- (address strategy , uint256 sharesToBurn ) = operatorSetBurnableShares.at (i);
178+ for (uint256 i = length; i >= 0 ; -- i) {
179+ decreaseBurnableShares (operatorSet, slashId, i - 1 );
180+ }
181+ }
182+
183+ /// @inheritdoc IStrategyManager
184+ function decreaseBurnableShares (OperatorSet calldata operatorSet , uint256 slashId , uint256 index ) public returns (uint256 ) {
185+ EnumerableMap.AddressToUintMap storage operatorSetBurnableShares =
186+ _operatorSetBurnableShares[operatorSet.key ()][slashId];
180187
181- // Remove the strategy from the operator set burnable shares.
182- operatorSetBurnableShares.remove (address (strategy));
188+ (address strategy , uint256 sharesToBurn ) = operatorSetBurnableShares.at (index);
183189
184- // Withdraw the shares to the slash escrow.
185- IStrategy (strategy).withdraw ({
186- recipient: address (slashEscrowFactory.getSlashEscrow (operatorSet, slashId)),
187- token: IStrategy (strategy).underlyingToken (),
188- amountShares: sharesToBurn
189- });
190+ // Withdraw the shares to the slash escrow.
191+ IStrategy (strategy).withdraw ({
192+ recipient: address (slashEscrowFactory.getSlashEscrow (operatorSet, slashId)),
193+ token: IStrategy (strategy).underlyingToken (),
194+ amountShares: sharesToBurn
195+ });
190196
191- // Emit an event to notify the that burnable shares have been decreased.
192- emit BurnOrRedistributableSharesDecreased (operatorSet, slashId, IStrategy (strategy), sharesToBurn);
193- }
197+ operatorSetBurnableShares.remove (address (strategy));
198+
199+ // Emit an event to notify the that burnable shares have been decreased.
200+ emit BurnOrRedistributableSharesDecreased (operatorSet, slashId, IStrategy (strategy), sharesToBurn);
201+
202+ return sharesToBurn;
194203 }
195204
196205 /// @inheritdoc IStrategyManager
@@ -208,6 +217,21 @@ contract StrategyManager is
208217 }
209218 }
210219
220+ /// @inheritdoc IStrategyManager
221+ function getBurnOrRedistributableShares (
222+ OperatorSet calldata operatorSet ,
223+ uint256 slashId
224+ ) external view returns (IStrategy[] memory ) {
225+ address [] memory keys = _operatorSetBurnableShares[operatorSet.key ()][slashId].keys ();
226+ IStrategy[] memory strategies = new IStrategy [](keys.length );
227+
228+ for (uint256 i = 0 ; i < keys.length ; ++ i) {
229+ strategies[i] = IStrategy (keys[i]);
230+ }
231+
232+ return strategies;
233+ }
234+
211235 /// @inheritdoc IStrategyManager
212236 function setStrategyWhitelister (
213237 address newStrategyWhitelister
0 commit comments