@@ -73,29 +73,7 @@ abstract contract Scheduler is IScheduler, SchedulerState {
7373
7474 // Check for permanent subscription restrictions
7575 if (currentParams.isPermanent) {
76- // Cannot disable isPermanent flag once set
77- if (! newParams.isPermanent) {
78- revert IllegalPermanentSubscriptionModification ();
79- }
80-
81- // Cannot remove price feeds from a permanent subscription
82- if (newParams.priceIds.length < currentParams.priceIds.length ) {
83- revert IllegalPermanentSubscriptionModification ();
84- }
85-
86- // Check that all existing price IDs are preserved
87- for (uint i = 0 ; i < currentParams.priceIds.length ; i++ ) {
88- bool found = false ;
89- for (uint j = 0 ; j < newParams.priceIds.length ; j++ ) {
90- if (currentParams.priceIds[i] == newParams.priceIds[j]) {
91- found = true ;
92- break ;
93- }
94- }
95- if (! found) {
96- revert IllegalPermanentSubscriptionModification ();
97- }
98- }
76+ _validatePermanentSubscriptionUpdate (currentParams, newParams);
9977 }
10078
10179 // If subscription is inactive and will remain inactive, no need to validate parameters
@@ -437,6 +415,103 @@ abstract contract Scheduler is IScheduler, SchedulerState {
437415 revert UpdateConditionsNotMet ();
438416 }
439417
418+ /**
419+ * @notice Internal helper to validate modifications to a permanent subscription.
420+ * @param currentParams The current subscription parameters (storage).
421+ * @param newParams The proposed new subscription parameters (memory).
422+ */
423+ function _validatePermanentSubscriptionUpdate (
424+ SubscriptionParams storage currentParams ,
425+ SubscriptionParams memory newParams
426+ ) internal view {
427+ // Cannot disable isPermanent flag once set
428+ if (! newParams.isPermanent) {
429+ revert IllegalPermanentSubscriptionModification ();
430+ }
431+
432+ // Cannot deactivate a permanent subscription
433+ if (! newParams.isActive) {
434+ revert IllegalPermanentSubscriptionModification ();
435+ }
436+
437+ // Cannot remove price feeds from a permanent subscription
438+ if (newParams.priceIds.length < currentParams.priceIds.length ) {
439+ revert IllegalPermanentSubscriptionModification ();
440+ }
441+
442+ // Check that all existing price IDs are preserved (adding is allowed, not removing)
443+ for (uint i = 0 ; i < currentParams.priceIds.length ; i++ ) {
444+ bool found = false ;
445+ for (uint j = 0 ; j < newParams.priceIds.length ; j++ ) {
446+ if (currentParams.priceIds[i] == newParams.priceIds[j]) {
447+ found = true ;
448+ break ;
449+ }
450+ }
451+ if (! found) {
452+ revert IllegalPermanentSubscriptionModification ();
453+ }
454+ }
455+
456+ // Cannot change reader whitelist settings for permanent subscriptions
457+ if (newParams.whitelistEnabled != currentParams.whitelistEnabled) {
458+ revert IllegalPermanentSubscriptionModification ();
459+ }
460+
461+ // Check if the set of addresses in the whitelist is the same
462+ if (
463+ newParams.readerWhitelist.length !=
464+ currentParams.readerWhitelist.length
465+ ) {
466+ revert IllegalPermanentSubscriptionModification ();
467+ }
468+ uint256 n = newParams.readerWhitelist.length ;
469+ bool [] memory currentVisited = new bool [](n);
470+ uint256 matchesFound = 0 ;
471+ for (uint256 i = 0 ; i < n; i++ ) {
472+ bool foundInCurrent = false ;
473+ for (uint256 j = 0 ; j < n; j++ ) {
474+ if (
475+ ! currentVisited[j] &&
476+ newParams.readerWhitelist[i] ==
477+ currentParams.readerWhitelist[j]
478+ ) {
479+ currentVisited[j] = true ;
480+ foundInCurrent = true ;
481+ matchesFound++ ;
482+ break ;
483+ }
484+ }
485+ if (! foundInCurrent) {
486+ revert IllegalPermanentSubscriptionModification ();
487+ }
488+ }
489+
490+ // Cannot change update criteria for permanent subscriptions
491+ if (
492+ newParams.updateCriteria.updateOnHeartbeat !=
493+ currentParams.updateCriteria.updateOnHeartbeat ||
494+ newParams.updateCriteria.heartbeatSeconds !=
495+ currentParams.updateCriteria.heartbeatSeconds ||
496+ newParams.updateCriteria.updateOnDeviation !=
497+ currentParams.updateCriteria.updateOnDeviation ||
498+ newParams.updateCriteria.deviationThresholdBps !=
499+ currentParams.updateCriteria.deviationThresholdBps
500+ ) {
501+ revert IllegalPermanentSubscriptionModification ();
502+ }
503+
504+ // Cannot change gas config for permanent subscriptions
505+ if (
506+ newParams.gasConfig.maxBaseFeeMultiplierCapPct !=
507+ currentParams.gasConfig.maxBaseFeeMultiplierCapPct ||
508+ newParams.gasConfig.maxPriorityFeeMultiplierCapPct !=
509+ currentParams.gasConfig.maxPriorityFeeMultiplierCapPct
510+ ) {
511+ revert IllegalPermanentSubscriptionModification ();
512+ }
513+ }
514+
440515 /// FETCH PRICES
441516
442517 /**
0 commit comments