Skip to content

Commit b2215f0

Browse files
committed
Merge branch 'tb/pulse-scheduler/init-address-reviews' of github.com:pyth-network/pyth-crosschain into tb/pulse-scheduler/init-address-reviews
2 parents 50bd1d6 + 1cb7116 commit b2215f0

File tree

6 files changed

+336
-76
lines changed

6 files changed

+336
-76
lines changed

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ interface IScheduler is SchedulerEvents {
1414
* @notice Adds a new subscription
1515
* @param subscriptionParams The parameters for the subscription
1616
* @return subscriptionId The ID of the newly created subscription
17+
* @dev Requires msg.value to be at least the minimum balance for the subscription
1718
*/
1819
function addSubscription(
1920
SchedulerState.SubscriptionParams calldata subscriptionParams
20-
) external returns (uint256 subscriptionId);
21+
) external payable returns (uint256 subscriptionId);
2122

2223
/**
2324
* @notice Gets a subscription's parameters and status
@@ -43,13 +44,9 @@ interface IScheduler is SchedulerEvents {
4344
function updateSubscription(
4445
uint256 subscriptionId,
4546
SchedulerState.SubscriptionParams calldata newSubscriptionParams
46-
) external;
47+
) external payable;
4748

48-
/**
49-
* @notice Deactivates a subscription
50-
* @param subscriptionId The ID of the subscription to deactivate
51-
*/
52-
function deactivateSubscription(uint256 subscriptionId) external;
49+
// Deactivation is now handled through updateSubscription by setting isActive to false
5350

5451
/**
5552
* @notice Updates price feeds for a subscription.
@@ -116,7 +113,7 @@ interface IScheduler is SchedulerEvents {
116113
*/
117114
function getMinimumBalance(
118115
uint8 numPriceFeeds
119-
) external returns (uint256 minimumBalance);
116+
) external view returns (uint256 minimumBalance);
120117

121118
/**
122119
* @notice Gets all active subscriptions with their parameters

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

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ abstract contract Scheduler is IScheduler, SchedulerState {
2222

2323
function addSubscription(
2424
SubscriptionParams memory subscriptionParams
25-
) external override returns (uint256 subscriptionId) {
25+
) external payable override returns (uint256 subscriptionId) {
2626
if (subscriptionParams.priceIds.length > MAX_PRICE_IDS) {
2727
revert TooManyPriceIds(
2828
subscriptionParams.priceIds.length,
@@ -51,6 +51,19 @@ abstract contract Scheduler is IScheduler, SchedulerState {
5151
.maxGasMultiplierCapPct = DEFAULT_MAX_GAS_MULTIPLIER_CAP_PCT;
5252
}
5353

54+
// Calculate minimum balance required for this subscription
55+
uint256 minimumBalance = this.getMinimumBalance(
56+
uint8(subscriptionParams.priceIds.length)
57+
);
58+
59+
// Ensure enough funds were provided
60+
if (msg.value < minimumBalance) {
61+
revert InsufficientBalance();
62+
}
63+
64+
// Set subscription to active
65+
subscriptionParams.isActive = true;
66+
5467
subscriptionId = _state.subscriptionNumber++;
5568

5669
// Store the subscription parameters
@@ -61,7 +74,7 @@ abstract contract Scheduler is IScheduler, SchedulerState {
6174
subscriptionId
6275
];
6376
status.priceLastUpdatedAt = 0;
64-
status.balanceInWei = 0;
77+
status.balanceInWei = msg.value;
6578
status.totalUpdates = 0;
6679
status.totalSpent = 0;
6780
status.isActive = true;
@@ -93,11 +106,22 @@ abstract contract Scheduler is IScheduler, SchedulerState {
93106
function updateSubscription(
94107
uint256 subscriptionId,
95108
SubscriptionParams memory newSubscriptionParams
96-
) external override onlyManager(subscriptionId) {
97-
if (!_state.subscriptionStatuses[subscriptionId].isActive) {
98-
revert InactiveSubscription();
109+
) external payable override onlyManager(subscriptionId) {
110+
SubscriptionStatus storage status = _state.subscriptionStatuses[
111+
subscriptionId
112+
];
113+
bool wasActive = status.isActive;
114+
bool willBeActive = newSubscriptionParams.isActive;
115+
116+
// If subscription is inactive and will remain inactive, no need to validate parameters
117+
if (!wasActive && !willBeActive) {
118+
// Update subscription parameters
119+
_state.subscriptionParams[subscriptionId] = newSubscriptionParams;
120+
emit SubscriptionUpdated(subscriptionId);
121+
return;
99122
}
100123

124+
// Validate parameters for active or to-be-activated subscriptions
101125
if (newSubscriptionParams.priceIds.length > MAX_PRICE_IDS) {
102126
revert TooManyPriceIds(
103127
newSubscriptionParams.priceIds.length,
@@ -126,24 +150,37 @@ abstract contract Scheduler is IScheduler, SchedulerState {
126150
.maxGasMultiplierCapPct = DEFAULT_MAX_GAS_MULTIPLIER_CAP_PCT;
127151
}
128152

129-
// Update subscription parameters
130-
_state.subscriptionParams[subscriptionId] = newSubscriptionParams;
153+
// Handle activation/deactivation
154+
if (!wasActive && willBeActive) {
155+
// Reactivating a subscription - ensure minimum balance
156+
uint256 minimumBalance = this.getMinimumBalance(
157+
uint8(newSubscriptionParams.priceIds.length)
158+
);
131159

132-
emit SubscriptionUpdated(subscriptionId);
133-
}
160+
// Add any funds sent with this transaction
161+
status.balanceInWei += msg.value;
134162

135-
function deactivateSubscription(
136-
uint256 subscriptionId
137-
) external override onlyManager(subscriptionId) {
138-
if (!_state.subscriptionStatuses[subscriptionId].isActive) {
139-
revert InactiveSubscription();
163+
// Check if balance meets minimum requirement
164+
if (status.balanceInWei < minimumBalance) {
165+
revert InsufficientBalance();
166+
}
167+
168+
status.isActive = true;
169+
emit SubscriptionActivated(subscriptionId);
170+
} else if (wasActive && !willBeActive) {
171+
// Deactivating a subscription
172+
status.isActive = false;
173+
emit SubscriptionDeactivated(subscriptionId);
140174
}
141175

142-
_state.subscriptionStatuses[subscriptionId].isActive = false;
176+
// Update subscription parameters
177+
_state.subscriptionParams[subscriptionId] = newSubscriptionParams;
143178

144-
emit SubscriptionDeactivated(subscriptionId);
179+
emit SubscriptionUpdated(subscriptionId);
145180
}
146181

182+
// Removed standalone deactivateSubscription function as it's now handled in updateSubscription
183+
147184
function updatePriceFeeds(
148185
uint256 subscriptionId,
149186
bytes[] calldata updateData,
@@ -439,11 +476,24 @@ abstract contract Scheduler is IScheduler, SchedulerState {
439476
SubscriptionStatus storage status = _state.subscriptionStatuses[
440477
subscriptionId
441478
];
479+
SubscriptionParams storage params = _state.subscriptionParams[
480+
subscriptionId
481+
];
442482

443483
if (status.balanceInWei < amount) {
444484
revert InsufficientBalance();
445485
}
446486

487+
// If subscription is active, ensure minimum balance is maintained
488+
if (status.isActive) {
489+
uint256 minimumBalance = this.getMinimumBalance(
490+
uint8(params.priceIds.length)
491+
);
492+
if (status.balanceInWei - amount < minimumBalance) {
493+
revert InsufficientBalance();
494+
}
495+
}
496+
447497
status.balanceInWei -= amount;
448498

449499
(bool sent, ) = msg.sender.call{value: amount}("");

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ interface SchedulerEvents {
1010
);
1111
event SubscriptionUpdated(uint256 indexed subscriptionId);
1212
event SubscriptionDeactivated(uint256 indexed subscriptionId);
13+
event SubscriptionActivated(uint256 indexed subscriptionId);
1314
event PricesUpdated(uint256 indexed subscriptionId, uint256 timestamp);
1415
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ contract SchedulerState {
3232
bytes32[] priceIds;
3333
address[] readerWhitelist;
3434
bool whitelistEnabled;
35+
bool isActive;
3536
UpdateCriteria updateCriteria;
3637
GasConfig gasConfig;
3738
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,19 @@ contract SchedulerUpgradeable is
6161
function version() public pure returns (string memory) {
6262
return "1.0.0";
6363
}
64+
65+
// Implementation of deactivateSubscription that forwards to updateSubscription
66+
function deactivateSubscription(
67+
uint256 subscriptionId
68+
) external onlyManager(subscriptionId) {
69+
// Get current subscription parameters
70+
SchedulerState.SubscriptionParams memory params = _state
71+
.subscriptionParams[subscriptionId];
72+
73+
// Set isActive to false
74+
params.isActive = false;
75+
76+
// Call updateSubscription to handle the deactivation
77+
this.updateSubscription(subscriptionId, params);
78+
}
6479
}

0 commit comments

Comments
 (0)