Skip to content

Commit 032e4a4

Browse files
authored
Merge pull request #1073 from graphprotocol/mde/trust-staking-fixes
2 parents 0c0d090 + 399b7a9 commit 032e4a4

26 files changed

+1325
-336
lines changed

packages/horizon/contracts/interfaces/internal/IHorizonStakingBase.sol

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ interface IHorizonStakingBase {
2424
*/
2525
event StakeDeposited(address indexed serviceProvider, uint256 tokens);
2626

27+
/**
28+
* @notice Thrown when using an invalid thaw request type.
29+
*/
30+
error HorizonStakingInvalidThawRequestType();
31+
2732
/**
2833
* @notice Gets the details of a service provider.
2934
* @param serviceProvider The address of the service provider.
@@ -134,34 +139,46 @@ interface IHorizonStakingBase {
134139

135140
/**
136141
* @notice Gets a thaw request.
142+
* @param thawRequestType The type of thaw request.
137143
* @param thawRequestId The id of the thaw request.
138144
* @return The thaw request details.
139145
*/
140-
function getThawRequest(bytes32 thawRequestId) external view returns (IHorizonStakingTypes.ThawRequest memory);
146+
function getThawRequest(
147+
IHorizonStakingTypes.ThawRequestType thawRequestType,
148+
bytes32 thawRequestId
149+
) external view returns (IHorizonStakingTypes.ThawRequest memory);
141150

142151
/**
143152
* @notice Gets the metadata of a thaw request list.
144153
* Service provider and delegators each have their own thaw request list per provision.
145154
* Metadata includes the head and tail of the list, plus the total number of thaw requests.
155+
* @param thawRequestType The type of thaw request.
146156
* @param serviceProvider The address of the service provider.
147157
* @param verifier The address of the verifier.
148158
* @param owner The owner of the thaw requests. Use either the service provider or delegator address.
149159
* @return The thaw requests list metadata.
150160
*/
151161
function getThawRequestList(
162+
IHorizonStakingTypes.ThawRequestType thawRequestType,
152163
address serviceProvider,
153164
address verifier,
154165
address owner
155166
) external view returns (LinkedList.List memory);
156167

157168
/**
158169
* @notice Gets the amount of thawed tokens for a given provision.
170+
* @param thawRequestType The type of thaw request.
159171
* @param serviceProvider The address of the service provider.
160172
* @param verifier The address of the verifier.
161173
* @param owner The owner of the thaw requests. Use either the service provider or delegator address.
162174
* @return The amount of thawed tokens.
163175
*/
164-
function getThawedTokens(address serviceProvider, address verifier, address owner) external view returns (uint256);
176+
function getThawedTokens(
177+
IHorizonStakingTypes.ThawRequestType thawRequestType,
178+
address serviceProvider,
179+
address verifier,
180+
address owner
181+
) external view returns (uint256);
165182

166183
/**
167184
* @notice Gets the maximum allowed thawing period for a provision.

packages/horizon/contracts/interfaces/internal/IHorizonStakingExtension.sol

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ interface IHorizonStakingExtension is IRewardsIssuer {
7777
uint256 delegationRewards
7878
);
7979

80+
/**
81+
* @dev Emitted when `indexer` was slashed for a total of `tokens` amount.
82+
* Tracks `reward` amount of tokens given to `beneficiary`.
83+
*/
84+
event StakeSlashed(address indexed indexer, uint256 tokens, uint256 reward, address beneficiary);
85+
8086
/**
8187
* @notice Close an allocation and free the staked tokens.
8288
* To be eligible for rewards a proof of indexing must be presented.
@@ -148,4 +154,14 @@ interface IHorizonStakingExtension is IRewardsIssuer {
148154
*/
149155
// solhint-disable-next-line func-name-mixedcase
150156
function __DEPRECATED_getThawingPeriod() external view returns (uint64);
157+
158+
/**
159+
* @notice Slash the indexer stake. Delegated tokens are not subject to slashing.
160+
* @dev Can only be called by the slasher role.
161+
* @param indexer Address of indexer to slash
162+
* @param tokens Amount of tokens to slash from the indexer stake
163+
* @param reward Amount of reward tokens to send to a beneficiary
164+
* @param beneficiary Address of a beneficiary to receive a reward for the slashing
165+
*/
166+
function legacySlash(address indexer, uint256 tokens, uint256 reward, address beneficiary) external;
151167
}

packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
pragma solidity 0.8.27;
44

55
import { IGraphPayments } from "../../interfaces/IGraphPayments.sol";
6+
import { IHorizonStakingTypes } from "./IHorizonStakingTypes.sol";
67

78
/**
89
* @title Inferface for the {HorizonStaking} contract.
@@ -205,6 +206,15 @@ interface IHorizonStakingMain {
205206
uint256 tokens
206207
);
207208

209+
/**
210+
* @notice Emitted when `delegator` withdrew delegated `tokens` from `indexer` using `withdrawDelegated`.
211+
* @dev This event is for the legacy `withdrawDelegated` function.
212+
* @param indexer The address of the indexer
213+
* @param delegator The address of the delegator
214+
* @param tokens The amount of tokens withdrawn
215+
*/
216+
event StakeDelegatedWithdrawn(address indexed indexer, address indexed delegator, uint256 tokens);
217+
208218
/**
209219
* @notice Emitted when tokens are added to a delegation pool's reserve.
210220
* @param serviceProvider The address of the service provider
@@ -271,13 +281,15 @@ interface IHorizonStakingMain {
271281
* @param owner The address of the owner of the thaw requests
272282
* @param thawRequestsFulfilled The number of thaw requests fulfilled
273283
* @param tokens The total amount of tokens being released
284+
* @param requestType The type of thaw request
274285
*/
275286
event ThawRequestsFulfilled(
276287
address indexed serviceProvider,
277288
address indexed verifier,
278289
address indexed owner,
279290
uint256 thawRequestsFulfilled,
280-
uint256 tokens
291+
uint256 tokens,
292+
IHorizonStakingTypes.ThawRequestType requestType
281293
);
282294

283295
// -- Events: governance --
@@ -303,9 +315,8 @@ interface IHorizonStakingMain {
303315

304316
/**
305317
* @notice Emitted when the delegation slashing global flag is set.
306-
* @param enabled Whether delegation slashing is enabled or disabled.
307318
*/
308-
event DelegationSlashingEnabled(bool enabled);
319+
event DelegationSlashingEnabled();
309320

310321
// -- Errors: tokens
311322

@@ -415,6 +426,20 @@ interface IHorizonStakingMain {
415426
*/
416427
error HorizonStakingInvalidDelegationPool(address serviceProvider, address verifier);
417428

429+
/**
430+
* @notice Thrown when the minimum token amount required for delegation is not met.
431+
* @param tokens The actual token amount
432+
* @param minTokens The minimum required token amount
433+
*/
434+
error HorizonStakingInsufficientDelegationTokens(uint256 tokens, uint256 minTokens);
435+
436+
/**
437+
* @notice Thrown when the minimum token amount required for undelegation with beneficiary is not met.
438+
* @param tokens The actual token amount
439+
* @param minTokens The minimum required token amount
440+
*/
441+
error HorizonStakingInsufficientUndelegationTokens(uint256 tokens, uint256 minTokens);
442+
418443
/**
419444
* @notice Thrown when attempting to undelegate with a beneficiary that is the zero address.
420445
*/
@@ -515,6 +540,8 @@ interface IHorizonStakingMain {
515540
* - During the transition period it's locked for a period of time before it can be withdrawn
516541
* by calling {withdraw}.
517542
* - After the transition period it's immediately withdrawn.
543+
* Note that after the transition period if there are tokens still locked they will have to be
544+
* withdrawn by calling {withdraw}.
518545
* @dev Requirements:
519546
* - `_tokens` cannot be zero.
520547
* - `_serviceProvider` must have enough idle stake to cover the staking amount and any
@@ -747,7 +774,7 @@ interface IHorizonStakingMain {
747774
* @param beneficiary The address where the tokens will be withdrawn after thawing
748775
* @return The ID of the thaw request
749776
*/
750-
function undelegate(
777+
function undelegateWithBeneficiary(
751778
address serviceProvider,
752779
address verifier,
753780
uint256 shares,
@@ -772,6 +799,28 @@ interface IHorizonStakingMain {
772799
*/
773800
function withdrawDelegated(address serviceProvider, address verifier, uint256 nThawRequests) external;
774801

802+
/**
803+
* @notice Withdraw undelegated with beneficiary tokens from a provision after thawing.
804+
* @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw
805+
* requests in the event that fulfilling all of them results in a gas limit error.
806+
* @dev If the delegation pool was completely slashed before withdrawing, calling this function will fulfill
807+
* the thaw requests with an amount equal to zero.
808+
*
809+
* Requirements:
810+
* - Must have previously initiated a thaw request using {undelegateWithBeneficiary}.
811+
*
812+
* Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled} and {DelegatedTokensWithdrawn} events.
813+
*
814+
* @param serviceProvider The service provider address
815+
* @param verifier The verifier address
816+
* @param nThawRequests The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests.
817+
*/
818+
function withdrawDelegatedWithBeneficiary(
819+
address serviceProvider,
820+
address verifier,
821+
uint256 nThawRequests
822+
) external;
823+
775824
/**
776825
* @notice Re-delegate undelegated tokens from a provision after thawing to a `newServiceProvider` and `newVerifier`.
777826
* @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw
@@ -838,13 +887,14 @@ interface IHorizonStakingMain {
838887
/**
839888
* @notice Withdraw undelegated tokens from the subgraph data service provision after thawing.
840889
* This function is for backwards compatibility with the legacy staking contract.
841-
* It only allows withdrawing from the subgraph data service and DOES NOT have slippage protection in
842-
* case the caller opts for re-delegating.
890+
* It only allows withdrawing tokens undelegated before horizon upgrade.
843891
* @dev See {delegate}.
844892
* @param serviceProvider The service provider address
845-
* @param newServiceProvider The address of a new service provider, if the delegator wants to re-delegate
846893
*/
847-
function withdrawDelegated(address serviceProvider, address newServiceProvider) external;
894+
function withdrawDelegated(
895+
address serviceProvider,
896+
address // newServiceProvider, deprecated
897+
) external returns (uint256);
848898

849899
/**
850900
* @notice Slash a service provider. This can only be called by a verifier to which

packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ interface IHorizonStakingTypes {
131131
uint256 __DEPRECATED_tokensLockedUntil;
132132
}
133133

134+
/**
135+
* @dev Enum to specify the type of thaw request.
136+
* @param Provision Represents a thaw request for a provision.
137+
* @param Delegation Represents a thaw request for a delegation.
138+
*/
139+
enum ThawRequestType {
140+
Provision,
141+
Delegation,
142+
DelegationWithBeneficiary
143+
}
144+
134145
/**
135146
* @notice Details of a stake thawing operation.
136147
* @dev ThawRequests are stored in linked lists by service provider/delegator,
@@ -146,4 +157,42 @@ interface IHorizonStakingTypes {
146157
// Used to invalidate unfulfilled thaw requests
147158
uint256 thawingNonce;
148159
}
160+
161+
/**
162+
* @notice Parameters to fulfill thaw requests.
163+
* @dev This struct is used to avoid stack too deep error in the `fulfillThawRequests` function.
164+
* @param requestType The type of thaw request (Provision or Delegation)
165+
* @param serviceProvider The address of the service provider
166+
* @param verifier The address of the verifier
167+
* @param owner The address of the owner of the thaw request
168+
* @param tokensThawing The current amount of tokens already thawing
169+
* @param sharesThawing The current amount of shares already thawing
170+
* @param nThawRequests The number of thaw requests to fulfill. If set to 0, all thaw requests are fulfilled.
171+
* @param thawingNonce The current valid thawing nonce. Any thaw request with a different nonce is invalid and should be ignored.
172+
*/
173+
struct FulfillThawRequestsParams {
174+
ThawRequestType requestType;
175+
address serviceProvider;
176+
address verifier;
177+
address owner;
178+
uint256 tokensThawing;
179+
uint256 sharesThawing;
180+
uint256 nThawRequests;
181+
uint256 thawingNonce;
182+
}
183+
184+
/**
185+
* @notice Results of the traversal of thaw requests.
186+
* @dev This struct is used to avoid stack too deep error in the `fulfillThawRequests` function.
187+
* @param requestsFulfilled The number of thaw requests fulfilled
188+
* @param tokensThawed The total amount of tokens thawed
189+
* @param tokensThawing The total amount of tokens thawing
190+
* @param sharesThawing The total amount of shares thawing
191+
*/
192+
struct TraverseThawRequestsResults {
193+
uint256 requestsFulfilled;
194+
uint256 tokensThawed;
195+
uint256 tokensThawing;
196+
uint256 sharesThawing;
197+
}
149198
}

0 commit comments

Comments
 (0)