Skip to content

Commit 99ca09c

Browse files
f: switch to uint64 timestamps
1 parent 8e15c54 commit 99ca09c

File tree

8 files changed

+95
-83
lines changed

8 files changed

+95
-83
lines changed

IndexingPaymentsTodo.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
# Still pending
22

33
* Arbitration Charter: Update to support disputing IndexingFee.
4-
* Expose a function that indexers can use to calculate the tokens to be collected and other collection params?
5-
* test_SubgraphService_CollectIndexingFee_Integration fails with PaymentsEscrowInconsistentCollection
6-
* Switch timestamps to uint64.
7-
* Check that UUID-v4 fits in `bytes16`
84
* Check code coverage
95
* Check contract size
10-
* Add upgrade path to v2 collector terms
11-
* It's more like a collect + cancel since the indexer is expected to stop work then and there. When posting a POI that's < N-1 epoch. Answer: Emit signal that the collection is meant to be final.
126
* Don't love cancel agreement on stop service / close stale allocation.
13-
* Place all agreement terms into one struct
147

158
# Done
169

10+
* DONE: ~~Switch cancel event in recurring collector to use Enum~~
11+
* DONE: ~~Switch timestamps to uint64~~
12+
* DONE: ~~Check that UUID-v4 fits in `bytes16`~~
1713
* DONE: ~~Double check cancelation policy. Who can cancel when? Right now is either party at any time. Answer: If gateway cancels allow collection till that point.~~
1814
* DONE: ~~If an indexer closes an allocation, what should happen to the accepeted agreement? Answer: Look into canceling agreement as part of stop service.~~
1915
* DONE: ~~Switch `duration` for `endsAt`? Answer: Do it.~~
@@ -39,3 +35,10 @@
3935
* DONE: ~~Unify to one error in Decoder.sol~~
4036
* DONE: ~~Built-in upgrade path to indexing agreements v2~~
4137
* DONE: ~~Missing events for accept, cancel, upgrade RCAs.~~
38+
39+
# Won't Fix
40+
41+
* Add upgrade path to v2 collector terms
42+
* Expose a function that indexers can use to calculate the tokens to be collected and other collection params?
43+
* Place all agreement terms into one struct
44+
* It's more like a collect + cancel since the indexer is expected to stop work then and there. When posting a POI that's < N-1 epoch. Answer: Emit signal that the collection is meant to be final. Counter: Won't do since collector can't signal back to data service that payment is maxed out. Could emit an event from the collector, but is it really worth it? Right now any collection where epoch POI < current POI is suspect.

packages/horizon/contracts/interfaces/IRecurringCollector.sol

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
3838
// The agreement ID of the RCA
3939
bytes16 agreementId;
4040
// The deadline for accepting the RCA
41-
uint256 deadline;
41+
uint64 deadline;
4242
// The timestamp when the agreement ends
43-
uint256 endsAt;
43+
uint64 endsAt;
4444
// The address of the payer the RCA was issued by
4545
address payer;
4646
// The address of the data service the RCA was issued to
@@ -73,9 +73,9 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
7373
// The agreement ID
7474
bytes16 agreementId;
7575
// The deadline for upgrading
76-
uint256 deadline;
76+
uint64 deadline;
7777
// The timestamp when the agreement ends
78-
uint256 endsAt;
78+
uint64 endsAt;
7979
// The maximum amount of tokens that can be collected in the first collection
8080
// on top of the amount allowed for subsequent collections
8181
uint256 maxInitialTokens;
@@ -99,11 +99,11 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
9999
// The address of the service provider
100100
address serviceProvider;
101101
// The timestamp when the agreement was accepted
102-
uint256 acceptedAt;
102+
uint64 acceptedAt;
103103
// The timestamp when the agreement was last collected at
104-
uint256 lastCollectionAt;
104+
uint64 lastCollectionAt;
105105
// The timestamp when the agreement ends
106-
uint256 endsAt;
106+
uint64 endsAt;
107107
// The maximum amount of tokens that can be collected in the first collection
108108
// on top of the amount allowed for subsequent collections
109109
uint256 maxInitialTokens;
@@ -115,7 +115,7 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
115115
// The maximum amount of seconds that can pass between collections
116116
uint32 maxSecondsPerCollection;
117117
// The timestamp when the agreement was canceled
118-
uint256 canceledAt;
118+
uint64 canceledAt;
119119
// The state of the agreement
120120
AgreementState state;
121121
}
@@ -149,8 +149,8 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
149149
address indexed payer,
150150
address indexed serviceProvider,
151151
bytes16 agreementId,
152-
uint256 acceptedAt,
153-
uint256 endsAt,
152+
uint64 acceptedAt,
153+
uint64 endsAt,
154154
uint256 maxInitialTokens,
155155
uint256 maxOngoingTokensPerSecond,
156156
uint32 minSecondsPerCollection,
@@ -162,14 +162,17 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
162162
* @param dataService The address of the data service
163163
* @param payer The address of the payer
164164
* @param serviceProvider The address of the service provider
165+
* @param agreementId The agreement ID
166+
* @param canceledAt The timestamp when the agreement was canceled
167+
* @param canceledBy The party that canceled the agreement
165168
*/
166169
event AgreementCanceled(
167170
address indexed dataService,
168171
address indexed payer,
169172
address indexed serviceProvider,
170173
bytes16 agreementId,
171-
uint256 canceledAt,
172-
address canceledBy
174+
uint64 canceledAt,
175+
CancelAgreementBy canceledBy
173176
);
174177

175178
/**
@@ -190,8 +193,8 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
190193
address indexed payer,
191194
address indexed serviceProvider,
192195
bytes16 agreementId,
193-
uint256 upgradedAt,
194-
uint256 endsAt,
196+
uint64 upgradedAt,
197+
uint64 endsAt,
195198
uint256 maxInitialTokens,
196199
uint256 maxOngoingTokensPerSecond,
197200
uint32 minSecondsPerCollection,
@@ -228,9 +231,9 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
228231

229232
/**
230233
* Thrown when interacting with an agreement with an elapsed deadline
231-
* @param elapsedAt The timestamp when the deadline elapsed
234+
* @param deadline The elapsed deadline timestamp
232235
*/
233-
error RecurringCollectorAgreementDeadlineElapsed(uint256 elapsedAt);
236+
error RecurringCollectorAgreementDeadlineElapsed(uint64 deadline);
234237

235238
/**
236239
* Thrown when the signer is invalid
@@ -273,23 +276,23 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
273276
* @param agreementId The agreement ID
274277
* @param endsAt The agreement end timestamp
275278
*/
276-
error RecurringCollectorAgreementElapsed(bytes16 agreementId, uint256 endsAt);
279+
error RecurringCollectorAgreementElapsed(bytes16 agreementId, uint64 endsAt);
277280

278281
/**
279282
* Thrown when calling collect() too soon
280283
* @param agreementId The agreement ID
281284
* @param secondsSinceLast Seconds since last collection
282285
* @param minSeconds Minimum seconds between collections
283286
*/
284-
error RecurringCollectorCollectionTooSoon(bytes16 agreementId, uint256 secondsSinceLast, uint256 minSeconds);
287+
error RecurringCollectorCollectionTooSoon(bytes16 agreementId, uint32 secondsSinceLast, uint32 minSeconds);
285288

286289
/**
287290
* Thrown when calling collect() too late
288291
* @param agreementId The agreement ID
289292
* @param secondsSinceLast Seconds since last collection
290293
* @param maxSeconds Maximum seconds between collections
291294
*/
292-
error RecurringCollectorCollectionTooLate(bytes16 agreementId, uint256 secondsSinceLast, uint256 maxSeconds);
295+
error RecurringCollectorCollectionTooLate(bytes16 agreementId, uint64 secondsSinceLast, uint32 maxSeconds);
293296

294297
/**
295298
* @dev Accept an indexing agreement.

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

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
9494
);
9595

9696
// accept the agreement
97-
agreement.acceptedAt = block.timestamp;
97+
agreement.acceptedAt = uint64(block.timestamp);
9898
agreement.state = AgreementState.Accepted;
9999
agreement.dataService = signedRCA.rca.dataService;
100100
agreement.payer = signedRCA.rca.payer;
@@ -135,25 +135,18 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
135135
agreement.dataService == msg.sender,
136136
RecurringCollectorDataServiceNotAuthorized(agreementId, msg.sender)
137137
);
138-
agreement.canceledAt = block.timestamp;
139-
address canceledBy;
140-
if (by == CancelAgreementBy.Payer) {
141-
agreement.state = AgreementState.CanceledByPayer;
142-
canceledBy = agreement.payer;
143-
} else if (by == CancelAgreementBy.ServiceProvider) {
144-
agreement.state = AgreementState.CanceledByServiceProvider;
145-
canceledBy = agreement.serviceProvider;
146-
} else {
147-
revert("invalid CancelAgreementBy");
148-
}
138+
agreement.canceledAt = uint64(block.timestamp);
139+
agreement.state = by == CancelAgreementBy.Payer
140+
? AgreementState.CanceledByPayer
141+
: AgreementState.CanceledByServiceProvider;
149142

150143
emit AgreementCanceled(
151144
agreement.dataService,
152145
agreement.payer,
153146
agreement.serviceProvider,
154147
agreementId,
155-
block.timestamp,
156-
canceledBy
148+
agreement.canceledAt,
149+
by
157150
);
158151
}
159152

@@ -194,7 +187,7 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
194187
agreement.payer,
195188
agreement.serviceProvider,
196189
signedRCAU.rcau.agreementId,
197-
block.timestamp,
190+
uint64(block.timestamp),
198191
agreement.endsAt,
199192
agreement.maxInitialTokens,
200193
agreement.maxOngoingTokensPerSecond,
@@ -284,7 +277,7 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
284277
_params.dataServiceCut
285278
);
286279
}
287-
agreement.lastCollectionAt = block.timestamp;
280+
agreement.lastCollectionAt = uint64(block.timestamp);
288281

289282
emit PaymentCollected(
290283
IGraphPayments.PaymentTypes.IndexingFee,
@@ -350,11 +343,19 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
350343
collectionSeconds -= _agreementCollectionStartAt(_agreement);
351344
require(
352345
collectionSeconds >= _agreement.minSecondsPerCollection,
353-
RecurringCollectorCollectionTooSoon(_agreementId, collectionSeconds, _agreement.minSecondsPerCollection)
346+
RecurringCollectorCollectionTooSoon(
347+
_agreementId,
348+
uint32(collectionSeconds),
349+
_agreement.minSecondsPerCollection
350+
)
354351
);
355352
require(
356353
collectionSeconds <= _agreement.maxSecondsPerCollection,
357-
RecurringCollectorCollectionTooLate(_agreementId, collectionSeconds, _agreement.maxSecondsPerCollection)
354+
RecurringCollectorCollectionTooLate(
355+
_agreementId,
356+
uint64(collectionSeconds),
357+
_agreement.maxSecondsPerCollection
358+
)
358359
);
359360

360361
uint256 maxTokens = _agreement.maxOngoingTokensPerSecond * collectionSeconds;

packages/horizon/test/payments/recurring-collector/RecurringCollectorHelper.t.sol

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,16 @@ contract RecurringCollectorHelper is AuthorizableHelper, Bounder {
4949
IRecurringCollector.RecurringCollectionAgreement memory rca
5050
) public view returns (IRecurringCollector.RecurringCollectionAgreement memory) {
5151
require(block.timestamp > 0, "block.timestamp can't be zero");
52-
rca.deadline = bound(rca.deadline, 0, block.timestamp - 1);
52+
require(block.timestamp <= type(uint64).max, "block.timestamp can't be huge");
53+
rca.deadline = uint64(bound(rca.deadline, 0, block.timestamp - 1));
5354
return rca;
5455
}
5556

5657
function withOKAcceptDeadline(
5758
IRecurringCollector.RecurringCollectionAgreement memory rca
5859
) public view returns (IRecurringCollector.RecurringCollectionAgreement memory) {
59-
rca.deadline = boundTimestampMin(rca.deadline, block.timestamp);
60+
require(block.timestamp <= type(uint64).max, "block.timestamp can't be huge");
61+
rca.deadline = uint64(boundTimestampMin(rca.deadline, block.timestamp));
6062
return rca;
6163
}
6264

@@ -100,16 +102,18 @@ contract RecurringCollectorHelper is AuthorizableHelper, Bounder {
100102
return rcau;
101103
}
102104

103-
function _sensibleDeadline(uint256 _seed) internal view returns (uint256) {
104-
return bound(_seed, block.timestamp + 1, block.timestamp + 7200); // between now and 2h
105+
function _sensibleDeadline(uint256 _seed) internal view returns (uint64) {
106+
return uint64(bound(_seed, block.timestamp + 1, block.timestamp + 7200)); // between now and 2h
105107
}
106108

107-
function _sensibleEndsAt(uint256 _seed, uint32 _maxSecondsPerCollection) internal view returns (uint256) {
109+
function _sensibleEndsAt(uint256 _seed, uint32 _maxSecondsPerCollection) internal view returns (uint64) {
108110
return
109-
bound(
110-
_seed,
111-
block.timestamp + (10 * uint256(_maxSecondsPerCollection)),
112-
block.timestamp + (1_000_000 * uint256(_maxSecondsPerCollection))
111+
uint64(
112+
bound(
113+
_seed,
114+
block.timestamp + (10 * uint256(_maxSecondsPerCollection)),
115+
block.timestamp + (1_000_000 * uint256(_maxSecondsPerCollection))
116+
)
113117
); // between 10 and 1M max collections
114118
}
115119

packages/horizon/test/payments/recurring-collector/accept.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ contract RecurringCollectorAcceptTest is RecurringCollectorSharedTest {
2121
uint256 unboundedSkip
2222
) public {
2323
vm.assume(fuzzySignedRCA.rca.agreementId != bytes16(0));
24-
skip(boundSkipFloor(unboundedSkip, 1));
24+
skip(boundSkip(unboundedSkip, 1, type(uint64).max - block.timestamp));
2525
fuzzySignedRCA.rca = _recurringCollectorHelper.withElapsedAcceptDeadline(fuzzySignedRCA.rca);
2626

2727
bytes memory expectedErr = abi.encodeWithSelector(

packages/horizon/test/payments/recurring-collector/shared.t.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ contract RecurringCollectorSharedTest is Test, Bounder {
7474
_signedRCA.rca.payer,
7575
_signedRCA.rca.serviceProvider,
7676
_signedRCA.rca.agreementId,
77-
block.timestamp,
77+
uint64(block.timestamp),
7878
_signedRCA.rca.endsAt,
7979
_signedRCA.rca.maxInitialTokens,
8080
_signedRCA.rca.maxOngoingTokensPerSecond,
@@ -95,8 +95,8 @@ contract RecurringCollectorSharedTest is Test, Bounder {
9595
_rca.payer,
9696
_rca.serviceProvider,
9797
_rca.agreementId,
98-
block.timestamp,
99-
_by == IRecurringCollector.CancelAgreementBy.Payer ? _rca.payer : _rca.serviceProvider
98+
uint64(block.timestamp),
99+
_by
100100
);
101101
vm.prank(_rca.dataService);
102102
_recurringCollector.cancel(_rca.agreementId, _by);

packages/horizon/test/payments/recurring-collector/upgrade.t.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ contract RecurringCollectorUpgradeTest is RecurringCollectorSharedTest {
2121
rcau = _recurringCollectorHelper.sensibleRCAU(rcau);
2222
rcau.agreementId = rca.agreementId;
2323

24-
boundSkipCeil(unboundedUpgradeSkip, type(uint256).max);
25-
rcau.deadline = bound(rcau.deadline, 0, block.timestamp - 1);
24+
boundSkipCeil(unboundedUpgradeSkip, type(uint64).max);
25+
rcau.deadline = uint64(bound(rcau.deadline, 0, block.timestamp - 1));
2626
IRecurringCollector.SignedRCAU memory signedRCAU = IRecurringCollector.SignedRCAU({
2727
rcau: rcau,
2828
signature: ""
@@ -45,7 +45,7 @@ contract RecurringCollectorUpgradeTest is RecurringCollectorSharedTest {
4545
rcau = _recurringCollectorHelper.sensibleRCAU(rcau);
4646
rcau.agreementId = rca.agreementId;
4747

48-
rcau.deadline = block.timestamp;
48+
rcau.deadline = uint64(block.timestamp);
4949
IRecurringCollector.SignedRCAU memory signedRCAU = IRecurringCollector.SignedRCAU({
5050
rcau: rcau,
5151
signature: ""
@@ -134,7 +134,7 @@ contract RecurringCollectorUpgradeTest is RecurringCollectorSharedTest {
134134
accepted.rca.payer,
135135
accepted.rca.serviceProvider,
136136
rcau.agreementId,
137-
block.timestamp,
137+
uint64(block.timestamp),
138138
rcau.endsAt,
139139
rcau.maxInitialTokens,
140140
rcau.maxOngoingTokensPerSecond,

0 commit comments

Comments
 (0)