Skip to content

Commit 3dc3140

Browse files
authored
Merge pull request #1097 from graphprotocol/mde/add-unique-id-to-collector-tracking
2 parents 8f922a1 + 2af2e68 commit 3dc3140

File tree

9 files changed

+428
-260
lines changed

9 files changed

+428
-260
lines changed

packages/horizon/contracts/interfaces/IPaymentsCollector.sol

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ interface IPaymentsCollector {
1717
/**
1818
* @notice Emitted when a payment is collected
1919
* @param paymentType The payment type collected as defined by {IGraphPayments}
20+
* @param collectionId The id for the collection. Can be used at the discretion of the collector to group multiple payments.
2021
* @param payer The address of the payer
2122
* @param receiver The address of the receiver
2223
* @param dataService The address of the data service
2324
* @param tokens The amount of tokens being collected
2425
*/
2526
event PaymentCollected(
26-
IGraphPayments.PaymentTypes indexed paymentType,
27+
IGraphPayments.PaymentTypes paymentType,
28+
bytes32 indexed collectionId,
2729
address indexed payer,
2830
address receiver,
2931
address indexed dataService,

packages/horizon/contracts/interfaces/ITAPCollector.sol

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ interface ITAPCollector is IPaymentsCollector {
2525

2626
/// @notice The Receipt Aggregate Voucher (RAV) struct
2727
struct ReceiptAggregateVoucher {
28+
// The ID of the collection "bucket" the RAV belongs to. Note that multiple RAVs can be collected for the same collection id.
29+
bytes32 collectionId;
2830
// The address of the payer the RAV was issued by
2931
address payer;
3032
// The address of the data service the RAV was issued to
@@ -80,6 +82,7 @@ interface ITAPCollector is IPaymentsCollector {
8082

8183
/**
8284
* @notice Emitted when a RAV is collected
85+
* @param collectionId The ID of the collection "bucket" the RAV belongs to.
8386
* @param payer The address of the payer
8487
* @param dataService The address of the data service
8588
* @param serviceProvider The address of the service provider
@@ -89,9 +92,10 @@ interface ITAPCollector is IPaymentsCollector {
8992
* @param signature The signature of the RAV
9093
*/
9194
event RAVCollected(
95+
bytes32 indexed collectionId,
9296
address indexed payer,
97+
address serviceProvider,
9398
address indexed dataService,
94-
address indexed serviceProvider,
9599
uint64 timestampNs,
96100
uint128 valueAggregate,
97101
bytes metadata,

packages/horizon/contracts/payments/collectors/TAPCollector.sol

+13-6
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector {
3535
/// @notice Authorization details for payer-signer pairs
3636
mapping(address signer => PayerAuthorization authorizedSigner) public authorizedSigners;
3737

38-
/// @notice Tracks the amount of tokens already collected by a data service from a payer to a receiver
39-
mapping(address dataService => mapping(address receiver => mapping(address payer => uint256 tokens)))
38+
/// @notice Tracks the amount of tokens already collected by a data service from a payer to a receiver.
39+
/// @dev The collectionId provides a secondary key for grouping payment tracking if needed. Data services that do not require
40+
/// grouping can use the same collectionId for all payments (0x00 or some other default value).
41+
mapping(address dataService => mapping(bytes32 collectionId => mapping(address receiver => mapping(address payer => uint256 tokens))))
4042
public tokensCollected;
4143

4244
/// @notice The duration (in seconds) in which a signer is thawing before they can be revoked
@@ -182,6 +184,7 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector {
182184
address payer = authorizedSigners[signer].payer;
183185
require(signedRAV.rav.payer == payer, TAPCollectorInvalidRAVPayer(payer, signedRAV.rav.payer));
184186

187+
bytes32 collectionId = signedRAV.rav.collectionId;
185188
address dataService = signedRAV.rav.dataService;
186189
address receiver = signedRAV.rav.serviceProvider;
187190

@@ -199,7 +202,7 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector {
199202
uint256 tokensToCollect = 0;
200203
{
201204
uint256 tokensRAV = signedRAV.rav.valueAggregate;
202-
uint256 tokensAlreadyCollected = tokensCollected[dataService][receiver][payer];
205+
uint256 tokensAlreadyCollected = tokensCollected[dataService][collectionId][receiver][payer];
203206
require(
204207
tokensRAV > tokensAlreadyCollected,
205208
TAPCollectorInconsistentRAVTokens(tokensRAV, tokensAlreadyCollected)
@@ -217,20 +220,24 @@ contract TAPCollector is EIP712, GraphDirectory, ITAPCollector {
217220
}
218221

219222
if (tokensToCollect > 0) {
220-
tokensCollected[dataService][receiver][payer] += tokensToCollect;
223+
tokensCollected[dataService][collectionId][receiver][payer] += tokensToCollect;
221224
_graphPaymentsEscrow().collect(_paymentType, payer, receiver, tokensToCollect, dataService, dataServiceCut);
222225
}
223226

224-
emit PaymentCollected(_paymentType, payer, receiver, dataService, tokensToCollect);
227+
emit PaymentCollected(_paymentType, collectionId, payer, receiver, dataService, tokensToCollect);
228+
229+
// This event is emitted to allow reconstructing RAV history with onchain data.
225230
emit RAVCollected(
231+
collectionId,
226232
payer,
227-
dataService,
228233
receiver,
234+
dataService,
229235
signedRAV.rav.timestampNs,
230236
signedRAV.rav.valueAggregate,
231237
signedRAV.rav.metadata,
232238
signedRAV.signature
233239
);
240+
234241
return tokensToCollect;
235242
}
236243

packages/horizon/test/payments/tap-collector/TAPCollector.t.sol

+5-1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ contract TAPCollectorTest is HorizonStakingSharedTest, PaymentsEscrowSharedTest
142142
(address _payer, , ) = tapCollector.authorizedSigners(_signer);
143143
uint256 tokensAlreadyCollected = tapCollector.tokensCollected(
144144
signedRAV.rav.dataService,
145+
signedRAV.rav.collectionId,
145146
signedRAV.rav.serviceProvider,
146147
_payer
147148
);
@@ -152,16 +153,18 @@ contract TAPCollectorTest is HorizonStakingSharedTest, PaymentsEscrowSharedTest
152153
vm.expectEmit(address(tapCollector));
153154
emit IPaymentsCollector.PaymentCollected(
154155
_paymentType,
156+
signedRAV.rav.collectionId,
155157
_payer,
156158
signedRAV.rav.serviceProvider,
157159
signedRAV.rav.dataService,
158160
tokensToCollect
159161
);
160162
vm.expectEmit(address(tapCollector));
161163
emit ITAPCollector.RAVCollected(
164+
signedRAV.rav.collectionId,
162165
_payer,
163-
signedRAV.rav.dataService,
164166
signedRAV.rav.serviceProvider,
167+
signedRAV.rav.dataService,
165168
signedRAV.rav.timestampNs,
166169
signedRAV.rav.valueAggregate,
167170
signedRAV.rav.metadata,
@@ -173,6 +176,7 @@ contract TAPCollectorTest is HorizonStakingSharedTest, PaymentsEscrowSharedTest
173176

174177
uint256 tokensCollectedAfter = tapCollector.tokensCollected(
175178
signedRAV.rav.dataService,
179+
signedRAV.rav.collectionId,
176180
signedRAV.rav.serviceProvider,
177181
_payer
178182
);

0 commit comments

Comments
 (0)