Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion target_chains/ethereum/contracts/contracts/pulse/Scheduler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ abstract contract Scheduler is IScheduler, SchedulerState {
subscriptionId
];

if (!status.isActive) {
if (!params.isActive) {
revert InactiveSubscription();
}

Expand All @@ -542,6 +542,16 @@ abstract contract Scheduler is IScheduler, SchedulerState {
}

status.balanceInWei += msg.value;

// If subscription is active, ensure minimum balance is maintained
if (params.isActive) {
uint256 minimumBalance = this.getMinimumBalance(
uint8(params.priceIds.length)
);
if (status.balanceInWei < minimumBalance) {
revert InsufficientBalance();
}
}
}

function withdrawFunds(
Expand Down
128 changes: 128 additions & 0 deletions target_chains/ethereum/contracts/forge-test/PulseScheduler.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,134 @@ contract SchedulerTest is Test, SchedulerEvents, PulseSchedulerTestUtils {
"Balance should match initial balance plus added funds"
);
}



function testAddFundsEnforcesMinimumBalance() public {
// First add a subscription with minimum balance
uint256 subscriptionId = addTestSubscription(
scheduler,
address(reader)
);

// Get subscription parameters and initial balance
(SchedulerState.SubscriptionParams memory params, SchedulerState.SubscriptionStatus memory status) = scheduler
.getSubscription(subscriptionId);

// Calculate minimum balance
uint256 minimumBalance = scheduler.getMinimumBalance(
uint8(params.priceIds.length)
);

// Verify initial balance is at minimum
assertEq(
status.balanceInWei,
minimumBalance,
"Initial balance should equal minimum balance"
);

// Add some funds to the subscription
uint256 additionalFunds = 0.1 ether;
scheduler.addFunds{value: additionalFunds}(subscriptionId);

// Verify funds were added
(, SchedulerState.SubscriptionStatus memory statusAfterAdd) = scheduler
.getSubscription(subscriptionId);
assertEq(
statusAfterAdd.balanceInWei,
minimumBalance + additionalFunds,
"Balance should be increased by the added funds"
);

// Now create a new subscription but don't fund it fully
SchedulerState.SubscriptionParams memory newParams = createDefaultSubscriptionParams(
2,
address(reader)
);

// Calculate minimum balance for this new subscription
uint256 newMinimumBalance = scheduler.getMinimumBalance(
uint8(newParams.priceIds.length)
);

// Try to create with insufficient funds
uint256 insufficientFunds = newMinimumBalance - 1 wei;
vm.expectRevert(abi.encodeWithSelector(InsufficientBalance.selector));
scheduler.createSubscription{value: insufficientFunds}(newParams);

// Create with sufficient funds
uint256 newSubscriptionId = scheduler.createSubscription{value: newMinimumBalance}(newParams);

// Verify subscription was created with minimum balance
(, SchedulerState.SubscriptionStatus memory newStatus) = scheduler
.getSubscription(newSubscriptionId);
assertEq(
newStatus.balanceInWei,
newMinimumBalance,
"New subscription balance should equal minimum balance"
);
}

function testAddFundsEnforcesMinimumBalanceForPermanentSubscription() public {
// Create a non-permanent subscription first
uint256 subscriptionId = addTestSubscription(
scheduler,
address(reader)
);

// Get subscription parameters and initial balance
(SchedulerState.SubscriptionParams memory params, SchedulerState.SubscriptionStatus memory status) = scheduler
.getSubscription(subscriptionId);

// Calculate minimum balance
uint256 minimumBalance = scheduler.getMinimumBalance(
uint8(params.priceIds.length)
);

// Verify initial balance is at minimum
assertEq(
status.balanceInWei,
minimumBalance,
"Initial balance should equal minimum balance"
);

// Make it permanent
params.isPermanent = true;
scheduler.updateSubscription(subscriptionId, params);

// Try to add funds - this should succeed since we're adding to a permanent subscription
uint256 additionalFunds = 0.1 ether;
scheduler.addFunds{value: additionalFunds}(subscriptionId);

// Verify funds were added
(, SchedulerState.SubscriptionStatus memory statusAfter) = scheduler
.getSubscription(subscriptionId);
assertEq(
statusAfter.balanceInWei,
minimumBalance + additionalFunds,
"Balance should be increased by the added funds"
);

// Now test the deposit limit for permanent subscriptions
uint256 maxDepositLimit = 100 ether; // MAX_DEPOSIT_LIMIT from SchedulerState

// Try to add funds exceeding the deposit limit
vm.expectRevert(abi.encodeWithSelector(MaxDepositLimitExceeded.selector));
scheduler.addFunds{value: maxDepositLimit + 1}(subscriptionId);

// Add funds within the deposit limit
uint256 validDeposit = 1 ether;
scheduler.addFunds{value: validDeposit}(subscriptionId);

// Verify funds were added
(, SchedulerState.SubscriptionStatus memory statusAfterValidDeposit) = scheduler
.getSubscription(subscriptionId);
assertEq(
statusAfterValidDeposit.balanceInWei,
minimumBalance + additionalFunds + validDeposit,
"Balance should be increased by the valid deposit"
);
}

function testWithdrawFunds() public {
// Add a subscription and get the parameters
Expand Down
Loading