@@ -503,6 +503,24 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
503
503
return indexerStake.tokensAvailableWithDelegation (tokensDelegated);
504
504
}
505
505
506
+ /**
507
+ * @dev Returns amount of delegated tokens ready to be withdrawn after unbonding period.
508
+ * @param _delegation Delegation of tokens from delegator to indexer
509
+ * @return Amount of tokens to withdraw
510
+ */
511
+ function getWithdraweableDelegatedTokens (Delegation memory _delegation )
512
+ public
513
+ view
514
+ returns (uint256 )
515
+ {
516
+ // There must be locked tokens and period passed
517
+ uint256 currentEpoch = epochManager ().currentEpoch ();
518
+ if (_delegation.tokensLockedUntil > 0 && currentEpoch >= _delegation.tokensLockedUntil) {
519
+ return _delegation.tokensLocked;
520
+ }
521
+ return 0 ;
522
+ }
523
+
506
524
/**
507
525
* @dev Authorize an address to be an operator.
508
526
* @param _operator Address to authorize
@@ -665,38 +683,14 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
665
683
/**
666
684
* @dev Withdraw delegated tokens once the unbonding period has passed.
667
685
* @param _indexer Withdraw available tokens delegated to indexer
668
- * @param _newIndexer Re-delegate to indexer address if non-zero, withdraw if zero address
686
+ * @param _delegateToIndexer Re-delegate to indexer address if non-zero, withdraw if zero address
669
687
*/
670
- function withdrawDelegated (address _indexer , address _newIndexer ) external override notPaused {
671
- address delegator = msg .sender ;
672
-
673
- // Get the delegation pool of the indexer
674
- DelegationPool storage pool = delegationPools[_indexer];
675
- Delegation storage delegation = pool.delegators[delegator];
676
-
677
- // There must be locked tokens and period passed
678
- uint256 currentEpoch = epochManager ().currentEpoch ();
679
- require (
680
- delegation.tokensLockedUntil > 0 && currentEpoch >= delegation.tokensLockedUntil,
681
- "No tokens available to withdraw "
682
- );
683
-
684
- // Get tokens available for withdrawal
685
- uint256 tokensToWithdraw = delegation.tokensLocked;
686
-
687
- // Reset lock
688
- delegation.tokensLocked = 0 ;
689
- delegation.tokensLockedUntil = 0 ;
690
-
691
- emit StakeDelegatedWithdrawn (_indexer, delegator, tokensToWithdraw);
692
-
693
- if (_newIndexer != address (0 )) {
694
- // Re-delegate tokens to a new indexer
695
- _delegate (delegator, _newIndexer, tokensToWithdraw);
696
- } else {
697
- // Return tokens to the delegator
698
- require (graphToken ().transfer (delegator, tokensToWithdraw), "!transfer " );
699
- }
688
+ function withdrawDelegated (address _indexer , address _delegateToIndexer )
689
+ external
690
+ override
691
+ notPaused
692
+ {
693
+ _withdrawDelegated (msg .sender , _indexer, _delegateToIndexer);
700
694
}
701
695
702
696
/**
@@ -1162,6 +1156,11 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1162
1156
// Delegator need to have enough shares in the pool to undelegate
1163
1157
require (delegation.shares >= _shares, "Delegator does not have enough shares " );
1164
1158
1159
+ // Withdraw tokens if available
1160
+ if (getWithdraweableDelegatedTokens (delegation) > 0 ) {
1161
+ _withdrawDelegated (_delegator, _indexer, address (0 ));
1162
+ }
1163
+
1165
1164
// Calculate tokens to get in exchange for the shares
1166
1165
uint256 tokens = _shares.mul (pool.tokens).div (pool.shares);
1167
1166
@@ -1185,6 +1184,44 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1185
1184
return tokens;
1186
1185
}
1187
1186
1187
+ /**
1188
+ * @dev Withdraw delegated tokens once the unbonding period has passed.
1189
+ * @param _delegator Delegator that is withdrawing tokens
1190
+ * @param _indexer Withdraw available tokens delegated to indexer
1191
+ * @param _delegateToIndexer Re-delegate to indexer address if non-zero, withdraw if zero address
1192
+ */
1193
+ function _withdrawDelegated (
1194
+ address _delegator ,
1195
+ address _indexer ,
1196
+ address _delegateToIndexer
1197
+ ) internal returns (uint256 ) {
1198
+ // Get the delegation pool of the indexer
1199
+ DelegationPool storage pool = delegationPools[_indexer];
1200
+ Delegation storage delegation = pool.delegators[_delegator];
1201
+
1202
+ // Validation
1203
+ uint256 tokensToWithdraw = getWithdraweableDelegatedTokens (delegation);
1204
+ require (tokensToWithdraw > 0 , "No tokens available to withdraw " );
1205
+
1206
+ // Reset lock
1207
+ delegation.tokensLocked = 0 ;
1208
+ delegation.tokensLockedUntil = 0 ;
1209
+
1210
+ emit StakeDelegatedWithdrawn (_indexer, _delegator, tokensToWithdraw);
1211
+
1212
+ // -- Effects --
1213
+
1214
+ if (_delegateToIndexer != address (0 )) {
1215
+ // Re-delegate tokens to a new indexer
1216
+ _delegate (_delegator, _delegateToIndexer, tokensToWithdraw);
1217
+ } else {
1218
+ // Return tokens to the delegator
1219
+ require (graphToken ().transfer (_delegator, tokensToWithdraw), "!transfer " );
1220
+ }
1221
+
1222
+ return tokensToWithdraw;
1223
+ }
1224
+
1188
1225
/**
1189
1226
* @dev Collect the delegation rewards for query fees.
1190
1227
* This function will assign the collected fees to the delegation pool.
0 commit comments