Skip to content

Commit 1451636

Browse files
fix(pulse-scheduler): disallow all updates to permanent subs, remove GasConfig (#2602)
* feat: disallow any config change to permanent feeds, remove gasconfig * doc: remove unnecessary comments * fix: consistency
1 parent ef3a901 commit 1451636

File tree

5 files changed

+33
-254
lines changed

5 files changed

+33
-254
lines changed

target_chains/ethereum/contracts/contracts/pulse/scheduler/Scheduler.sol

Lines changed: 11 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,21 @@ abstract contract Scheduler is IScheduler, SchedulerState {
6464
uint256 subscriptionId,
6565
SubscriptionParams memory newParams
6666
) external override onlyManager(subscriptionId) {
67-
SchedulerState.SubscriptionStatus storage currentStatus = _state
68-
.subscriptionStatuses[subscriptionId];
69-
SchedulerState.SubscriptionParams storage currentParams = _state
70-
.subscriptionParams[subscriptionId];
71-
bool wasActive = currentParams.isActive;
72-
bool willBeActive = newParams.isActive;
67+
SubscriptionStatus storage currentStatus = _state.subscriptionStatuses[
68+
subscriptionId
69+
];
70+
SubscriptionParams storage currentParams = _state.subscriptionParams[
71+
subscriptionId
72+
];
7373

74-
// Check for permanent subscription restrictions
74+
// Updates to permanent subscriptions are not allowed
7575
if (currentParams.isPermanent) {
76-
_validatePermanentSubscriptionUpdate(currentParams, newParams);
76+
revert CannotUpdatePermanentSubscription();
7777
}
7878

7979
// If subscription is inactive and will remain inactive, no need to validate parameters
80+
bool wasActive = currentParams.isActive;
81+
bool willBeActive = newParams.isActive;
8082
if (!wasActive && !willBeActive) {
8183
// Update subscription parameters
8284
_state.subscriptionParams[subscriptionId] = newParams;
@@ -182,19 +184,6 @@ abstract contract Scheduler is IScheduler, SchedulerState {
182184
) {
183185
revert InvalidUpdateCriteria();
184186
}
185-
186-
// If gas config is unset, set it to the default (100x multipliers)
187-
if (
188-
params.gasConfig.maxBaseFeeMultiplierCapPct == 0 ||
189-
params.gasConfig.maxPriorityFeeMultiplierCapPct == 0
190-
) {
191-
params
192-
.gasConfig
193-
.maxPriorityFeeMultiplierCapPct = DEFAULT_MAX_PRIORITY_FEE_MULTIPLIER_CAP_PCT;
194-
params
195-
.gasConfig
196-
.maxBaseFeeMultiplierCapPct = DEFAULT_MAX_BASE_FEE_MULTIPLIER_CAP_PCT;
197-
}
198187
}
199188

200189
/**
@@ -415,103 +404,6 @@ abstract contract Scheduler is IScheduler, SchedulerState {
415404
revert UpdateConditionsNotMet();
416405
}
417406

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-
515407
/// FETCH PRICES
516408

517409
/**
@@ -635,7 +527,7 @@ abstract contract Scheduler is IScheduler, SchedulerState {
635527

636528
// Prevent withdrawals from permanent subscriptions
637529
if (params.isPermanent) {
638-
revert IllegalPermanentSubscriptionModification();
530+
revert CannotUpdatePermanentSubscription();
639531
}
640532

641533
if (status.balanceInWei < amount) {

target_chains/ethereum/contracts/contracts/pulse/scheduler/SchedulerErrors.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ error Unauthorized();
88
// Subscription state errors
99
error InactiveSubscription();
1010
error InsufficientBalance();
11-
error IllegalPermanentSubscriptionModification();
11+
error CannotUpdatePermanentSubscription();
1212

1313
// Price feed errors
1414
error InvalidPriceId(bytes32 providedPriceId, bytes32 expectedPriceId);
@@ -20,7 +20,6 @@ error PriceSlotMismatch();
2020

2121
// Update criteria errors
2222
error InvalidUpdateCriteria();
23-
error InvalidGasConfig();
2423
error UpdateConditionsNotMet();
2524
error TimestampOlderThanLastUpdate(
2625
uint256 providedUpdateTimestamp,

target_chains/ethereum/contracts/contracts/pulse/scheduler/SchedulerState.sol

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ contract SchedulerState {
99
uint8 public constant MAX_PRICE_IDS_PER_SUBSCRIPTION = 255;
1010
/// Maximum number of addresses in the reader whitelist
1111
uint8 public constant MAX_READER_WHITELIST_SIZE = 255;
12-
/// Default max gas multiplier
13-
uint32 public constant DEFAULT_MAX_BASE_FEE_MULTIPLIER_CAP_PCT = 10_000;
14-
/// Default max fee multiplier
15-
uint32 public constant DEFAULT_MAX_PRIORITY_FEE_MULTIPLIER_CAP_PCT = 10_000;
1612

1713
// TODO: make these updateable via governance
1814
/// Maximum time in the past (relative to current block timestamp)
@@ -45,7 +41,6 @@ contract SchedulerState {
4541
bool isActive;
4642
bool isPermanent;
4743
UpdateCriteria updateCriteria;
48-
GasConfig gasConfig;
4944
}
5045

5146
struct SubscriptionStatus {
@@ -55,19 +50,6 @@ contract SchedulerState {
5550
uint256 totalSpent;
5651
}
5752

58-
/// @dev When pushing prices, providers will use a "fast gas" estimation as default.
59-
/// If the gas is insufficient to land the transaction, the provider will linearly scale
60-
/// base fee and priority fee multipliers until the transaction lands.
61-
/// These parameters allow the subscriber to impose limits on these multipliers.
62-
/// For example, with maxBaseFeeMultiplierCapPct = 10_000 (default), the provider can
63-
/// use a max of 100x (10000%) of the estimated gas as reported by the RPC.
64-
struct GasConfig {
65-
/// Base gas fee price multiplier limit percent for update operations
66-
uint32 maxBaseFeeMultiplierCapPct;
67-
/// Priority fee multiplier limit for update operations
68-
uint32 maxPriorityFeeMultiplierCapPct;
69-
}
70-
7153
struct UpdateCriteria {
7254
bool updateOnHeartbeat;
7355
uint32 heartbeatSeconds;

0 commit comments

Comments
 (0)