Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -433,18 +433,6 @@ interface IHorizonStakingMain {
*/
error HorizonStakingInsufficientDelegationTokens(uint256 tokens, uint256 minTokens);

/**
* @notice Thrown when the minimum token amount required for undelegation with beneficiary is not met.
* @param tokens The actual token amount
* @param minTokens The minimum required token amount
*/
error HorizonStakingInsufficientUndelegationTokens(uint256 tokens, uint256 minTokens);

/**
* @notice Thrown when attempting to undelegate with a beneficiary that is the zero address.
*/
error HorizonStakingInvalidBeneficiaryZeroAddress();

/**
* @notice Thrown when attempting to redelegate with a serivce provider that is the zero address.
*/
Expand Down Expand Up @@ -754,33 +742,6 @@ interface IHorizonStakingMain {
*/
function undelegate(address serviceProvider, address verifier, uint256 shares) external returns (bytes32);

/**
* @notice Undelegate tokens from a provision and start thawing them.
* The tokens will be withdrawable by the `beneficiary` after the thawing period.
*
* Note that undelegating tokens from a provision is a two step process:
* - First the tokens are thawed using this function.
* - Then after the thawing period, the tokens are removed from the provision using {withdrawDelegated}.
*
* Requirements:
* - `shares` cannot be zero.
* - `beneficiary` cannot be the zero address.
*
* Emits a {TokensUndelegated} and {ThawRequestCreated} event.
*
* @param serviceProvider The service provider address
* @param verifier The verifier address
* @param shares The amount of shares to undelegate
* @param beneficiary The address where the tokens will be withdrawn after thawing
* @return The ID of the thaw request
*/
// function undelegateWithBeneficiary(
// address serviceProvider,
// address verifier,
// uint256 shares,
// address beneficiary
// ) external returns (bytes32);

/**
* @notice Withdraw undelegated tokens from a provision after thawing.
* @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw
Expand All @@ -799,28 +760,6 @@ interface IHorizonStakingMain {
*/
function withdrawDelegated(address serviceProvider, address verifier, uint256 nThawRequests) external;

/**
* @notice Withdraw undelegated with beneficiary tokens from a provision after thawing.
* @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw
* requests in the event that fulfilling all of them results in a gas limit error.
* @dev If the delegation pool was completely slashed before withdrawing, calling this function will fulfill
* the thaw requests with an amount equal to zero.
*
* Requirements:
* - Must have previously initiated a thaw request using {undelegateWithBeneficiary}.
*
* Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled} and {DelegatedTokensWithdrawn} events.
*
* @param serviceProvider The service provider address
* @param verifier The verifier address
* @param nThawRequests The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests.
*/
// function withdrawDelegatedWithBeneficiary(
// address serviceProvider,
// address verifier,
// uint256 nThawRequests
// ) external;

/**
* @notice Re-delegate undelegated tokens from a provision after thawing to a `newServiceProvider` and `newVerifier`.
* @dev The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ interface IHorizonStakingTypes {
*/
enum ThawRequestType {
Provision,
Delegation,
DelegationWithBeneficiary
Delegation
}

/**
Expand Down
55 changes: 0 additions & 55 deletions packages/horizon/contracts/staking/HorizonStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain {
/// @dev Minimum amount of delegation.
uint256 private constant MIN_DELEGATION = 1e18;

/// @dev Minimum amount of undelegation with beneficiary.
uint256 private constant MIN_UNDELEGATION_WITH_BENEFICIARY = 10e18;

/**
* @notice Checks that the caller is authorized to operate over a provision.
* @param serviceProvider The address of the service provider.
Expand Down Expand Up @@ -307,19 +304,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain {
return _undelegate(ThawRequestType.Delegation, serviceProvider, verifier, shares, msg.sender);
}

/**
* @notice See {IHorizonStakingMain-undelegate}.
*/
// function undelegateWithBeneficiary(
// address serviceProvider,
// address verifier,
// uint256 shares,
// address beneficiary
// ) external override notPaused returns (bytes32) {
// require(beneficiary != address(0), HorizonStakingInvalidBeneficiaryZeroAddress());
// return _undelegate(ThawRequestType.DelegationWithBeneficiary, serviceProvider, verifier, shares, beneficiary);
// }

/**
* @notice See {IHorizonStakingMain-withdrawDelegated}.
*/
Expand All @@ -339,25 +323,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain {
);
}

/**
* @notice See {IHorizonStakingMain-withdrawDelegatedWithBeneficiary}.
*/
// function withdrawDelegatedWithBeneficiary(
// address serviceProvider,
// address verifier,
// uint256 nThawRequests
// ) external override notPaused {
// _withdrawDelegated(
// ThawRequestType.DelegationWithBeneficiary,
// serviceProvider,
// verifier,
// address(0),
// address(0),
// 0,
// nThawRequests
// );
// }

/**
* @notice See {IHorizonStakingMain-redelegate}.
*/
Expand Down Expand Up @@ -935,16 +900,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain {
// Thawing pool is reset/initialized when the pool is empty: prov.tokensThawing == 0
uint256 tokens = (_shares * (pool.tokens - pool.tokensThawing)) / pool.shares;

// Since anyone can undelegate for any beneficiary, we require a minimum amount to prevent
// malicious actors from flooding the thaw request list with tiny amounts and causing a
// denial of service attack by hitting the MAX_THAW_REQUESTS limit
if (_requestType == ThawRequestType.DelegationWithBeneficiary) {
require(
tokens >= MIN_UNDELEGATION_WITH_BENEFICIARY,
HorizonStakingInsufficientUndelegationTokens(tokens, MIN_UNDELEGATION_WITH_BENEFICIARY)
);
}

// Thawing shares are rounded down to protect the pool and avoid taking extra tokens from other participants.
uint256 thawingShares = pool.tokensThawing == 0 ? tokens : ((tokens * pool.sharesThawing) / pool.tokensThawing);
uint64 thawingUntil = uint64(block.timestamp + uint256(_provisions[_serviceProvider][_verifier].thawingPeriod));
Expand Down Expand Up @@ -1208,8 +1163,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain {
return _deleteProvisionThawRequest;
} else if (_requestType == ThawRequestType.Delegation) {
return _deleteDelegationThawRequest;
} else if (_requestType == ThawRequestType.DelegationWithBeneficiary) {
return _deleteDelegationWithBeneficiaryThawRequest;
} else {
revert HorizonStakingInvalidThawRequestType();
}
Expand All @@ -1231,14 +1184,6 @@ contract HorizonStaking is HorizonStakingBase, IHorizonStakingMain {
delete _thawRequests[ThawRequestType.Delegation][_thawRequestId];
}

/**
* @notice Deletes a thaw request for a delegation with a beneficiary.
* @param _thawRequestId The ID of the thaw request to delete.
*/
function _deleteDelegationWithBeneficiaryThawRequest(bytes32 _thawRequestId) private {
delete _thawRequests[ThawRequestType.DelegationWithBeneficiary][_thawRequestId];
}

/**
* @notice See {IHorizonStakingMain-setOperator}.
* @dev Note that this function handles the special case where the verifier is the subgraph data service,
Expand Down
11 changes: 0 additions & 11 deletions packages/horizon/contracts/staking/HorizonStakingBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,6 @@ abstract contract HorizonStakingBase is
return _getNextProvisionThawRequest;
} else if (_requestType == ThawRequestType.Delegation) {
return _getNextDelegationThawRequest;
} else if (_requestType == ThawRequestType.DelegationWithBeneficiary) {
return _getNextDelegationWithBeneficiaryThawRequest;
} else {
revert HorizonStakingInvalidThawRequestType();
}
Expand All @@ -335,15 +333,6 @@ abstract contract HorizonStakingBase is
return _thawRequests[ThawRequestType.Delegation][_thawRequestId].next;
}

/**
* @notice Retrieves the next thaw request for a delegation with a beneficiary.
* @param _thawRequestId The ID of the current thaw request.
* @return The ID of the next thaw request in the list.
*/
function _getNextDelegationWithBeneficiaryThawRequest(bytes32 _thawRequestId) internal view returns (bytes32) {
return _thawRequests[ThawRequestType.DelegationWithBeneficiary][_thawRequestId].next;
}

/**
* @notice Retrieves the thaw request list for the given request type.
* @dev Uses the `ThawRequestType` to determine which mapping to access.
Expand Down
2 changes: 1 addition & 1 deletion packages/horizon/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ test = 'test'
cache_path = 'cache_forge'
fs_permissions = [{ access = "read", path = "./"}]
optimizer = true
optimizer_runs = 200
optimizer_runs = 50
Original file line number Diff line number Diff line change
Expand Up @@ -908,17 +908,6 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest {
__undelegate(IHorizonStakingTypes.ThawRequestType.Delegation, serviceProvider, verifier, shares, false, caller);
}

function _undelegateWithBeneficiary(address serviceProvider, address verifier, uint256 shares, address beneficiary) internal {
__undelegate(
IHorizonStakingTypes.ThawRequestType.DelegationWithBeneficiary,
serviceProvider,
verifier,
shares,
false,
beneficiary
);
}

function _undelegate(address serviceProvider, uint256 shares) internal {
(, address caller, ) = vm.readCallers();
__undelegate(
Expand Down Expand Up @@ -992,8 +981,6 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest {
staking.undelegate(serviceProvider, shares);
} else if (thawRequestType == IHorizonStakingTypes.ThawRequestType.Delegation) {
staking.undelegate(serviceProvider, verifier, shares);
} else if (thawRequestType == IHorizonStakingTypes.ThawRequestType.DelegationWithBeneficiary) {
staking.undelegateWithBeneficiary(serviceProvider, verifier, shares, beneficiary);
} else {
revert("Invalid thaw request type");
}
Expand Down Expand Up @@ -1053,24 +1040,6 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest {
__withdrawDelegated(params);
}

function _withdrawDelegatedWithBeneficiary(
address serviceProvider,
address verifier,
uint256 nThawRequests
) internal {
Params_WithdrawDelegated memory params = Params_WithdrawDelegated({
thawRequestType: IHorizonStakingTypes.ThawRequestType.DelegationWithBeneficiary,
serviceProvider: serviceProvider,
verifier: verifier,
newServiceProvider: address(0),
newVerifier: address(0),
minSharesForNewProvider: 0,
nThawRequests: nThawRequests,
legacy: false
});
__withdrawDelegated(params);
}

function _redelegate(
address serviceProvider,
address verifier,
Expand Down Expand Up @@ -1197,8 +1166,6 @@ abstract contract HorizonStakingSharedTest is GraphBaseTest {
);
} else if (params.thawRequestType == IHorizonStakingTypes.ThawRequestType.Delegation) {
staking.withdrawDelegated(params.serviceProvider, params.verifier, params.nThawRequests);
} else if (params.thawRequestType == IHorizonStakingTypes.ThawRequestType.DelegationWithBeneficiary) {
staking.withdrawDelegatedWithBeneficiary(params.serviceProvider, params.verifier, params.nThawRequests);
} else {
revert("Invalid thaw request type");
}
Expand Down
23 changes: 0 additions & 23 deletions packages/horizon/test/staking/delegation/undelegate.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,6 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest {
_undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares);
}

function testUndelegate_WithBeneficiary(
uint256 amount,
uint256 delegationAmount,
address beneficiary
) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) {
vm.assume(beneficiary != address(0));
vm.assume(delegationAmount >= MIN_UNDELEGATION_WITH_BENEFICIARY);
resetPrank(users.delegator);
DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false);
_undelegateWithBeneficiary(users.indexer, subgraphDataServiceAddress, delegation.shares, beneficiary);
}

function testUndelegate_RevertWhen_InsuficientTokens(
uint256 amount,
uint256 delegationAmount,
Expand Down Expand Up @@ -255,15 +243,4 @@ contract HorizonStakingUndelegateTest is HorizonStakingTest {
resetPrank(users.delegator);
_undelegate(users.indexer, subgraphDataServiceAddress, delegation.shares - delegation.shares / 2);
}

function testUndelegate_RevertIf_BeneficiaryIsZero(
uint256 amount,
uint256 delegationAmount
) public useIndexer useProvision(amount, 0, 0) useDelegation(delegationAmount) {
resetPrank(users.delegator);
DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false);
bytes memory expectedError = abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingInvalidBeneficiaryZeroAddress.selector);
vm.expectRevert(expectedError);
staking.undelegateWithBeneficiary(users.indexer, subgraphDataServiceAddress, delegation.shares, address(0));
}
}
59 changes: 0 additions & 59 deletions packages/horizon/test/staking/delegation/withdraw.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -155,63 +155,4 @@ contract HorizonStakingWithdrawDelegationTest is HorizonStakingTest {
resetPrank(users.delegator);
_withdrawDelegated(users.indexer, subgraphDataServiceAddress, 0);
}

function testWithdrawDelegation_WithBeneficiary(
uint256 delegationAmount,
address beneficiary
)
public
useIndexer
useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD)
useDelegation(delegationAmount)
{
vm.assume(beneficiary != address(0));
vm.assume(beneficiary != address(staking));
vm.assume(delegationAmount >= MIN_UNDELEGATION_WITH_BENEFICIARY);
// Skip beneficiary if balance will overflow
vm.assume(token.balanceOf(beneficiary) < type(uint256).max - delegationAmount);

// Delegator undelegates to beneficiary
resetPrank(users.delegator);
DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false);
_undelegateWithBeneficiary(users.indexer, subgraphDataServiceAddress, delegation.shares, beneficiary);

// Thawing period ends
LinkedList.List memory thawingRequests = staking.getThawRequestList(IHorizonStakingTypes.ThawRequestType.Delegation, users.indexer, subgraphDataServiceAddress, beneficiary);
ThawRequest memory thawRequest = staking.getThawRequest(IHorizonStakingTypes.ThawRequestType.Delegation, thawingRequests.tail);
skip(thawRequest.thawingUntil + 1);

// Beneficiary withdraws delegated tokens
resetPrank(beneficiary);
_withdrawDelegatedWithBeneficiary(users.indexer, subgraphDataServiceAddress, 1);
}

function testWithdrawDelegation_RevertWhen_PreviousOwnerAttemptsToWithdraw(
uint256 delegationAmount,
address beneficiary
)
public
useIndexer
useProvision(10_000_000 ether, 0, MAX_THAWING_PERIOD)
useDelegation(delegationAmount)
{
vm.assume(beneficiary != address(0));
vm.assume(beneficiary != users.delegator);
vm.assume(delegationAmount >= MIN_UNDELEGATION_WITH_BENEFICIARY);

// Delegator undelegates to beneficiary
resetPrank(users.delegator);
DelegationInternal memory delegation = _getStorage_Delegation(users.indexer, subgraphDataServiceAddress, users.delegator, false);
_undelegateWithBeneficiary(users.indexer, subgraphDataServiceAddress, delegation.shares, beneficiary);

// Thawing period ends
LinkedList.List memory thawingRequests = staking.getThawRequestList(IHorizonStakingTypes.ThawRequestType.Delegation, users.indexer, subgraphDataServiceAddress, users.delegator);
ThawRequest memory thawRequest = staking.getThawRequest(IHorizonStakingTypes.ThawRequestType.Delegation, thawingRequests.tail);
skip(thawRequest.thawingUntil + 1);

// Delegator attempts to withdraw delegated tokens, should revert since beneficiary is the thaw request owner
bytes memory expectedError = abi.encodeWithSelector(IHorizonStakingMain.HorizonStakingNothingThawing.selector);
vm.expectRevert(expectedError);
staking.withdrawDelegated(users.indexer, subgraphDataServiceAddress, 1);
}
}
1 change: 0 additions & 1 deletion packages/horizon/test/utils/Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ abstract contract Constants {
uint64 internal constant MAX_THAWING_PERIOD = 28 days;
uint32 internal constant THAWING_PERIOD_IN_BLOCKS = 300;
uint256 internal constant MIN_DELEGATION = 1e18;
uint256 internal constant MIN_UNDELEGATION_WITH_BENEFICIARY = 10e18;
// Epoch manager
uint256 internal constant EPOCH_LENGTH = 1;
// Rewards manager
Expand Down
Loading
Loading