diff --git a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts index 2cd1de5da..2bc14338a 100644 --- a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts +++ b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts @@ -34,7 +34,7 @@ export const solidityUserConfig: SolidityUserConfig = { settings: { optimizer: { enabled: true, - runs: 1, + runs: 100, }, }, } diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol index 6252f63fa..31e42de44 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingMain.sol @@ -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. */ @@ -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 @@ -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 diff --git a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol index e2376bf18..416a82eba 100644 --- a/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol +++ b/packages/horizon/contracts/interfaces/internal/IHorizonStakingTypes.sol @@ -138,8 +138,7 @@ interface IHorizonStakingTypes { */ enum ThawRequestType { Provision, - Delegation, - DelegationWithBeneficiary + Delegation } /** diff --git a/packages/horizon/contracts/staking/HorizonStaking.sol b/packages/horizon/contracts/staking/HorizonStaking.sol index 97fb30ca9..5bd41c19b 100644 --- a/packages/horizon/contracts/staking/HorizonStaking.sol +++ b/packages/horizon/contracts/staking/HorizonStaking.sol @@ -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. @@ -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}. */ @@ -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}. */ @@ -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)); @@ -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(); } @@ -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, diff --git a/packages/horizon/contracts/staking/HorizonStakingBase.sol b/packages/horizon/contracts/staking/HorizonStakingBase.sol index 5f2808255..72a2167e1 100644 --- a/packages/horizon/contracts/staking/HorizonStakingBase.sol +++ b/packages/horizon/contracts/staking/HorizonStakingBase.sol @@ -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(); } @@ -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. diff --git a/packages/horizon/foundry.toml b/packages/horizon/foundry.toml index 56cb8a0b6..552938288 100644 --- a/packages/horizon/foundry.toml +++ b/packages/horizon/foundry.toml @@ -6,4 +6,4 @@ test = 'test' cache_path = 'cache_forge' fs_permissions = [{ access = "read", path = "./"}] optimizer = true -optimizer_runs = 200 \ No newline at end of file +optimizer_runs = 100 \ No newline at end of file diff --git a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol index 3be6633fb..e63adb021 100644 --- a/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol +++ b/packages/horizon/test/shared/horizon-staking/HorizonStakingShared.t.sol @@ -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( @@ -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"); } @@ -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, @@ -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"); } diff --git a/packages/horizon/test/staking/delegation/undelegate.t.sol b/packages/horizon/test/staking/delegation/undelegate.t.sol index e23fdadb8..af9e7b319 100644 --- a/packages/horizon/test/staking/delegation/undelegate.t.sol +++ b/packages/horizon/test/staking/delegation/undelegate.t.sol @@ -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, @@ -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)); - } } diff --git a/packages/horizon/test/staking/delegation/withdraw.t.sol b/packages/horizon/test/staking/delegation/withdraw.t.sol index ab286c279..010f710a5 100644 --- a/packages/horizon/test/staking/delegation/withdraw.t.sol +++ b/packages/horizon/test/staking/delegation/withdraw.t.sol @@ -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); - } } diff --git a/packages/horizon/test/utils/Constants.sol b/packages/horizon/test/utils/Constants.sol index e74e3b0d1..0c4721c67 100644 --- a/packages/horizon/test/utils/Constants.sol +++ b/packages/horizon/test/utils/Constants.sol @@ -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 diff --git a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol index f11e18d1b..0a36af020 100644 --- a/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol +++ b/packages/subgraph-service/contracts/utilities/AllocationManagerStorage.sol @@ -6,10 +6,10 @@ import { LegacyAllocation } from "../libraries/LegacyAllocation.sol"; abstract contract AllocationManagerV1Storage { /// @notice Allocation details - mapping(address allocationId => Allocation.State allocation) public allocations; + mapping(address allocationId => Allocation.State allocation) internal allocations; /// @notice Legacy allocation details - mapping(address allocationId => LegacyAllocation.State allocation) public legacyAllocations; + mapping(address allocationId => LegacyAllocation.State allocation) internal legacyAllocations; /// @notice Tracks allocated tokens per indexer mapping(address indexer => uint256 tokens) public allocationProvisionTracker; @@ -22,7 +22,7 @@ abstract contract AllocationManagerV1Storage { /// @notice Track total tokens allocated per subgraph deployment /// @dev Used to calculate indexing rewards - mapping(bytes32 subgraphDeploymentId => uint256 tokens) public subgraphAllocatedTokens; + mapping(bytes32 subgraphDeploymentId => uint256 tokens) internal subgraphAllocatedTokens; /// @dev Gap to allow adding variables in future upgrades uint256[50] private __gap; diff --git a/packages/subgraph-service/foundry.toml b/packages/subgraph-service/foundry.toml index 90444cf44..d70cbf59d 100644 --- a/packages/subgraph-service/foundry.toml +++ b/packages/subgraph-service/foundry.toml @@ -6,4 +6,4 @@ test = 'test' cache_path = 'cache_forge' fs_permissions = [{ access = "read", path = "./"}] optimizer = true -optimizer-runs = 50 +optimizer-runs = 100