Skip to content

Commit 4fa4ca4

Browse files
f: fix underflow
1 parent 348c162 commit 4fa4ca4

File tree

3 files changed

+14
-3
lines changed

3 files changed

+14
-3
lines changed

packages/horizon/contracts/interfaces/IRecurringCollector.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,14 @@ interface IRecurringCollector is IAuthorizable, IPaymentsCollector {
259259
*/
260260
error RecurringCollectorInvalidCollectData(bytes invalidData);
261261

262+
/**
263+
* Thrown when calling collect() on a payer canceled agreement
264+
* where the final collection has already been done
265+
* @param agreementId The agreement ID
266+
* @param finalCollectionAt The timestamp when the final collection was done
267+
*/
268+
error RecurringCollectorFinalCollectionDone(bytes16 agreementId, uint256 finalCollectionAt);
269+
262270
/**
263271
* Thrown when interacting with an agreement that has an incorrect state
264272
* @param agreementId The agreement ID

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,13 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
340340
bytes16 _agreementId,
341341
uint256 _tokens
342342
) private view returns (uint256) {
343-
uint256 collectionSeconds = _agreement.state == AgreementState.CanceledByPayer
343+
// if canceled by the payer allow collection up to the cancelation time
344+
uint256 collectionEnd = _agreement.state == AgreementState.CanceledByPayer
344345
? _agreement.canceledAt
345346
: block.timestamp;
346-
collectionSeconds -= _agreementCollectionStartAt(_agreement);
347+
uint256 collectionStart = _agreementCollectionStartAt(_agreement);
348+
require(collectionEnd > collectionStart, RecurringCollectorFinalCollectionDone(_agreementId, collectionStart));
349+
uint256 collectionSeconds = collectionEnd - collectionStart;
347350
require(
348351
collectionSeconds >= _agreement.minSecondsPerCollection,
349352
RecurringCollectorCollectionTooSoon(

packages/horizon/test/unit/payments/recurring-collector/collect.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ contract RecurringCollectorCollectTest is RecurringCollectorSharedTest {
142142
vm.prank(accepted.rca.dataService);
143143
_recurringCollector.collect(IGraphPayments.PaymentTypes.IndexingFee, data);
144144

145-
uint256 collectionSeconds = boundSkipCeil(unboundedCollectionSeconds, accepted.rca.minSecondsPerCollection - 1);
145+
uint256 collectionSeconds = boundSkip(unboundedCollectionSeconds, 1, accepted.rca.minSecondsPerCollection - 1);
146146
skip(collectionSeconds);
147147

148148
IRecurringCollector.CollectParams memory collectParams = _generateCollectParams(

0 commit comments

Comments
 (0)