Skip to content

feat: implement Indexing Agreements [Pending Audit] #1134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: tmigone/horizon-fixes-june
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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 @@ -5,6 +5,7 @@ import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol";

import { ProvisionTracker } from "../libraries/ProvisionTracker.sol";
import { LinkedList } from "../../libraries/LinkedList.sol";
import { StakeClaims } from "../libraries/StakeClaims.sol";

import { DataService } from "../DataService.sol";
import { DataServiceFeesV1Storage } from "./DataServiceFeesStorage.sol";
Expand Down Expand Up @@ -41,23 +42,17 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat
* @param _unlockTimestamp The timestamp when the tokens can be released
*/
function _lockStake(address _serviceProvider, uint256 _tokens, uint256 _unlockTimestamp) internal {
require(_tokens != 0, DataServiceFeesZeroTokens());
feesProvisionTracker.lock(_graphStaking(), _serviceProvider, _tokens, _delegationRatio);

LinkedList.List storage claimsList = claimsLists[_serviceProvider];

// Save item and add to list
bytes32 claimId = _buildStakeClaimId(_serviceProvider, claimsList.nonce);
claims[claimId] = StakeClaim({
tokens: _tokens,
createdAt: block.timestamp,
releasableAt: _unlockTimestamp,
nextClaim: bytes32(0)
});
if (claimsList.count != 0) claims[claimsList.tail].nextClaim = claimId;
claimsList.addTail(claimId);

emit StakeClaimLocked(_serviceProvider, claimId, _tokens, _unlockTimestamp);
StakeClaims.lockStake(
feesProvisionTracker,
claims,
claimsLists,
_graphStaking(),
address(this),
_delegationRatio,
_serviceProvider,
_tokens,
_unlockTimestamp
);
}

/**
Expand All @@ -80,7 +75,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat
_numClaimsToRelease
);

emit StakeClaimsReleased(_serviceProvider, claimsReleased, abi.decode(data, (uint256)));
emit StakeClaims.StakeClaimsReleased(_serviceProvider, claimsReleased, abi.decode(data, (uint256)));
}

/**
Expand All @@ -92,23 +87,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat
* @return The updated accumulator data
*/
function _processStakeClaim(bytes32 _claimId, bytes memory _acc) private returns (bool, bytes memory) {
StakeClaim memory claim = _getStakeClaim(_claimId);

// early exit
if (claim.releasableAt > block.timestamp) {
return (true, LinkedList.NULL_BYTES);
}

// decode
(uint256 tokensClaimed, address serviceProvider) = abi.decode(_acc, (uint256, address));

// process
feesProvisionTracker.release(serviceProvider, claim.tokens);
emit StakeClaimReleased(serviceProvider, _claimId, claim.tokens, claim.releasableAt);

// encode
_acc = abi.encode(tokensClaimed + claim.tokens, serviceProvider);
return (false, _acc);
return StakeClaims.processStakeClaim(feesProvisionTracker, claims, _claimId, _acc);
}

/**
Expand All @@ -117,18 +96,7 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat
* @param _claimId The ID of the stake claim to delete
*/
function _deleteStakeClaim(bytes32 _claimId) private {
delete claims[_claimId];
}

/**
* @notice Gets the details of a stake claim
* @param _claimId The ID of the stake claim
* @return The stake claim details
*/
function _getStakeClaim(bytes32 _claimId) private view returns (StakeClaim memory) {
StakeClaim memory claim = claims[_claimId];
require(claim.createdAt != 0, DataServiceFeesClaimNotFound(_claimId));
return claim;
StakeClaims.deleteStakeClaim(claims, _claimId);
}

/**
Expand All @@ -138,16 +106,6 @@ abstract contract DataServiceFees is DataService, DataServiceFeesV1Storage, IDat
* @return The next stake claim ID
*/
function _getNextStakeClaim(bytes32 _claimId) private view returns (bytes32) {
return claims[_claimId].nextClaim;
}

/**
* @notice Builds a stake claim ID
* @param _serviceProvider The address of the service provider
* @param _nonce A nonce of the stake claim
* @return The stake claim ID
*/
function _buildStakeClaimId(address _serviceProvider, uint256 _nonce) private view returns (bytes32) {
return keccak256(abi.encodePacked(address(this), _serviceProvider, _nonce));
return StakeClaims.getNextStakeClaim(claims, _claimId);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.27;

import { IDataServiceFees } from "../interfaces/IDataServiceFees.sol";
import { StakeClaims } from "../libraries/StakeClaims.sol";

import { LinkedList } from "../../libraries/LinkedList.sol";

Expand All @@ -15,7 +15,7 @@ abstract contract DataServiceFeesV1Storage {
mapping(address serviceProvider => uint256 tokens) public feesProvisionTracker;

/// @notice List of all locked stake claims to be released to service providers
mapping(bytes32 claimId => IDataServiceFees.StakeClaim claim) public claims;
mapping(bytes32 claimId => StakeClaims.StakeClaim claim) public claims;

/// @notice Service providers registered in the data service
mapping(address serviceProvider => LinkedList.List list) public claimsLists;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,70 +22,6 @@ import { IDataService } from "./IDataService.sol";
* bugs. We may have an active bug bounty program.
*/
interface IDataServiceFees is IDataService {
/**
* @notice A stake claim, representing provisioned stake that gets locked
* to be released to a service provider.
* @dev StakeClaims are stored in linked lists by service provider, ordered by
* creation timestamp.
* @param tokens The amount of tokens to be locked in the claim
* @param createdAt The timestamp when the claim was created
* @param releasableAt The timestamp when the tokens can be released
* @param nextClaim The next claim in the linked list
*/
struct StakeClaim {
uint256 tokens;
uint256 createdAt;
uint256 releasableAt;
bytes32 nextClaim;
}

/**
* @notice Emitted when a stake claim is created and stake is locked.
* @param serviceProvider The address of the service provider
* @param claimId The id of the stake claim
* @param tokens The amount of tokens to lock in the claim
* @param unlockTimestamp The timestamp when the tokens can be released
*/
event StakeClaimLocked(
address indexed serviceProvider,
bytes32 indexed claimId,
uint256 tokens,
uint256 unlockTimestamp
);

/**
* @notice Emitted when a stake claim is released and stake is unlocked.
* @param serviceProvider The address of the service provider
* @param claimId The id of the stake claim
* @param tokens The amount of tokens released
* @param releasableAt The timestamp when the tokens were released
*/
event StakeClaimReleased(
address indexed serviceProvider,
bytes32 indexed claimId,
uint256 tokens,
uint256 releasableAt
);

/**
* @notice Emitted when a series of stake claims are released.
* @param serviceProvider The address of the service provider
* @param claimsCount The number of stake claims being released
* @param tokensReleased The total amount of tokens being released
*/
event StakeClaimsReleased(address indexed serviceProvider, uint256 claimsCount, uint256 tokensReleased);

/**
* @notice Thrown when attempting to get a stake claim that does not exist.
* @param claimId The id of the stake claim
*/
error DataServiceFeesClaimNotFound(bytes32 claimId);

/**
* @notice Emitted when trying to lock zero tokens in a stake claim
*/
error DataServiceFeesZeroTokens();

/**
* @notice Releases expired stake claims for the caller.
* @dev This function is only meant to be called if the service provider has enough
Expand Down
Loading