@@ -26,6 +26,12 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
26
26
"RecurringCollectionAgreement(bytes16 agreementId,uint256 acceptDeadline,uint256 duration,address payer,address dataService,address serviceProvider,uint256 maxInitialTokens,uint256 maxOngoingTokensPerSecond,uint32 minSecondsPerCollection,uint32 maxSecondsPerCollection,bytes metadata) "
27
27
);
28
28
29
+ /// @notice The EIP712 typehash for the RecurringCollectionAgreementUpgrade struct
30
+ bytes32 public constant EIP712_RCAU_TYPEHASH =
31
+ keccak256 (
32
+ "RecurringCollectionAgreementUpgrade(bytes16 agreementId,uint256 acceptDeadline,uint256 duration,uint256 maxInitialTokens,uint256 maxOngoingTokensPerSecond,uint32 minSecondsPerCollection,uint32 maxSecondsPerCollection,bytes metadata) "
33
+ );
34
+
29
35
/// @notice Sentinel value to indicate an agreement has been canceled
30
36
uint256 public constant CANCELED = type (uint256 ).max;
31
37
@@ -68,7 +74,7 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
68
74
* See {IRecurringCollector.accept}.
69
75
* @dev Caller must be the data service the RCA was issued to.
70
76
*/
71
- function accept (SignedRCA memory signedRCA ) external {
77
+ function accept (SignedRCA calldata signedRCA ) external {
72
78
require (
73
79
msg .sender == signedRCA.rca.dataService,
74
80
RecurringCollectorCallerNotDataService (msg .sender , signedRCA.rca.dataService)
@@ -116,10 +122,31 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
116
122
/**
117
123
* @notice Upgrade an indexing agreement.
118
124
* See {IRecurringCollector.upgrade}.
119
- * @dev Caller must be the data service the RCA was issued to .
125
+ * @dev Caller must be the data service for the agreement .
120
126
*/
121
- function upgrade () external {
122
- // FIX-ME: implement me
127
+ function upgrade (SignedRCAU calldata signedRCAU ) external {
128
+ require (
129
+ signedRCAU.rcau.acceptDeadline >= block .timestamp ,
130
+ RecurringCollectorAgreementAcceptanceElapsed (signedRCAU.rcau.acceptDeadline)
131
+ );
132
+
133
+ AgreementData storage agreement = _getForUpdateAgreement (signedRCAU.rcau.agreementId);
134
+ require (agreement.acceptedAt > 0 , RecurringCollectorAgreementNeverAccepted (signedRCAU.rcau.agreementId));
135
+ require (
136
+ agreement.dataService == msg .sender ,
137
+ RecurringCollectorDataServiceNotAuthorized (signedRCAU.rcau.agreementId, msg .sender )
138
+ );
139
+
140
+ // check that the voucher is signed by the payer (or proxy)
141
+ _requireAuthorizedRCAUSigner (signedRCAU, agreement.payer);
142
+
143
+ // upgrade the agreement
144
+ // FIX-ME: These need to be validated to something that makes sense for the contract
145
+ agreement.duration = signedRCAU.rcau.duration;
146
+ agreement.maxInitialTokens = signedRCAU.rcau.maxInitialTokens;
147
+ agreement.maxOngoingTokensPerSecond = signedRCAU.rcau.maxOngoingTokensPerSecond;
148
+ agreement.minSecondsPerCollection = signedRCAU.rcau.minSecondsPerCollection;
149
+ agreement.maxSecondsPerCollection = signedRCAU.rcau.maxSecondsPerCollection;
123
150
}
124
151
125
152
/**
@@ -129,13 +156,27 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
129
156
return _recoverRCASigner (signedRCA);
130
157
}
131
158
159
+ /**
160
+ * @notice See {IRecurringCollector.recoverRCAUSigner}
161
+ */
162
+ function recoverRCAUSigner (SignedRCAU calldata signedRCAU ) external view returns (address ) {
163
+ return _recoverRCAUSigner (signedRCAU);
164
+ }
165
+
132
166
/**
133
167
* @notice See {IRecurringCollector.encodeRCA}
134
168
*/
135
169
function encodeRCA (RecurringCollectionAgreement calldata rca ) external view returns (bytes32 ) {
136
170
return _encodeRCA (rca);
137
171
}
138
172
173
+ /**
174
+ * @notice See {IRecurringCollector.encodeRCAU}
175
+ */
176
+ function encodeRCAU (RecurringCollectionAgreementUpgrade calldata rcau ) external view returns (bytes32 ) {
177
+ return _encodeRCAU (rcau);
178
+ }
179
+
139
180
/**
140
181
* @notice Decodes the collect data.
141
182
*/
@@ -235,6 +276,14 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
235
276
return ECDSA.recover (messageHash, _signedRCA.signature);
236
277
}
237
278
279
+ /**
280
+ * @notice See {IRecurringCollector.recoverRCAUSigner}
281
+ */
282
+ function _recoverRCAUSigner (SignedRCAU memory _signedRCAU ) private view returns (address ) {
283
+ bytes32 messageHash = _encodeRCAU (_signedRCAU.rcau);
284
+ return ECDSA.recover (messageHash, _signedRCAU.signature);
285
+ }
286
+
238
287
/**
239
288
* @notice See {IRecurringCollector.encodeRCA}
240
289
*/
@@ -260,13 +309,49 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
260
309
);
261
310
}
262
311
312
+ /**
313
+ * @notice See {IRecurringCollector.encodeRCAU}
314
+ */
315
+ function _encodeRCAU (RecurringCollectionAgreementUpgrade memory _rcau ) private view returns (bytes32 ) {
316
+ return
317
+ _hashTypedDataV4 (
318
+ keccak256 (
319
+ abi.encode (
320
+ EIP712_RCAU_TYPEHASH,
321
+ _rcau.agreementId,
322
+ _rcau.acceptDeadline,
323
+ _rcau.duration,
324
+ _rcau.maxInitialTokens,
325
+ _rcau.maxOngoingTokensPerSecond,
326
+ _rcau.minSecondsPerCollection,
327
+ _rcau.maxSecondsPerCollection,
328
+ keccak256 (_rcau.metadata)
329
+ )
330
+ )
331
+ );
332
+ }
333
+
263
334
/**
264
335
* @notice Requires that the signer for the RCA is authorized
265
336
* by the payer of the RCA.
266
337
*/
267
338
function _requireAuthorizedRCASigner (SignedRCA memory _signedRCA ) private view returns (address ) {
268
339
address signer = _recoverRCASigner (_signedRCA);
269
- require (_isAuthorized (_signedRCA.rca.payer, signer), RecurringCollectorInvalidRCASigner ());
340
+ require (_isAuthorized (_signedRCA.rca.payer, signer), RecurringCollectorInvalidSigner ());
341
+
342
+ return signer;
343
+ }
344
+
345
+ /**
346
+ * @notice Requires that the signer for the RCAU is authorized
347
+ * by the payer.
348
+ */
349
+ function _requireAuthorizedRCAUSigner (
350
+ SignedRCAU memory _signedRCAU ,
351
+ address _payer
352
+ ) private view returns (address ) {
353
+ address signer = _recoverRCAUSigner (_signedRCAU);
354
+ require (_isAuthorized (_payer, signer), RecurringCollectorInvalidSigner ());
270
355
271
356
return signer;
272
357
}
0 commit comments