@@ -26,6 +26,12 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
2626 "RecurringCollectionAgreement(bytes16 agreementId,uint256 acceptDeadline,uint256 duration,address payer,address dataService,address serviceProvider,uint256 maxInitialTokens,uint256 maxOngoingTokensPerSecond,uint32 minSecondsPerCollection,uint32 maxSecondsPerCollection,bytes metadata) "
2727 );
2828
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+
2935 /// @notice Sentinel value to indicate an agreement has been canceled
3036 uint256 public constant CANCELED = type (uint256 ).max;
3137
@@ -68,7 +74,7 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
6874 * See {IRecurringCollector.accept}.
6975 * @dev Caller must be the data service the RCA was issued to.
7076 */
71- function accept (SignedRCA memory signedRCA ) external {
77+ function accept (SignedRCA calldata signedRCA ) external {
7278 require (
7379 msg .sender == signedRCA.rca.dataService,
7480 RecurringCollectorCallerNotDataService (msg .sender , signedRCA.rca.dataService)
@@ -116,10 +122,31 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
116122 /**
117123 * @notice Upgrade an indexing agreement.
118124 * 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 .
120126 */
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;
123150 }
124151
125152 /**
@@ -129,13 +156,27 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
129156 return _recoverRCASigner (signedRCA);
130157 }
131158
159+ /**
160+ * @notice See {IRecurringCollector.recoverRCAUSigner}
161+ */
162+ function recoverRCAUSigner (SignedRCAU calldata signedRCAU ) external view returns (address ) {
163+ return _recoverRCAUSigner (signedRCAU);
164+ }
165+
132166 /**
133167 * @notice See {IRecurringCollector.encodeRCA}
134168 */
135169 function encodeRCA (RecurringCollectionAgreement calldata rca ) external view returns (bytes32 ) {
136170 return _encodeRCA (rca);
137171 }
138172
173+ /**
174+ * @notice See {IRecurringCollector.encodeRCAU}
175+ */
176+ function encodeRCAU (RecurringCollectionAgreementUpgrade calldata rcau ) external view returns (bytes32 ) {
177+ return _encodeRCAU (rcau);
178+ }
179+
139180 /**
140181 * @notice Decodes the collect data.
141182 */
@@ -235,6 +276,14 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
235276 return ECDSA.recover (messageHash, _signedRCA.signature);
236277 }
237278
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+
238287 /**
239288 * @notice See {IRecurringCollector.encodeRCA}
240289 */
@@ -260,13 +309,49 @@ contract RecurringCollector is EIP712, GraphDirectory, Authorizable, IRecurringC
260309 );
261310 }
262311
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+
263334 /**
264335 * @notice Requires that the signer for the RCA is authorized
265336 * by the payer of the RCA.
266337 */
267338 function _requireAuthorizedRCASigner (SignedRCA memory _signedRCA ) private view returns (address ) {
268339 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 ());
270355
271356 return signer;
272357 }
0 commit comments