Skip to content

Commit 2ee0169

Browse files
fix: ensure subscription balance is greater than minimum balance after adding funds
Co-Authored-By: Tejas Badadare <tejas@dourolabs.xyz>
1 parent 422dca8 commit 2ee0169

File tree

2 files changed

+139
-1
lines changed

2 files changed

+139
-1
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ abstract contract Scheduler is IScheduler, SchedulerState {
531531
subscriptionId
532532
];
533533

534-
if (!status.isActive) {
534+
if (!params.isActive) {
535535
revert InactiveSubscription();
536536
}
537537

@@ -542,6 +542,16 @@ abstract contract Scheduler is IScheduler, SchedulerState {
542542
}
543543

544544
status.balanceInWei += msg.value;
545+
546+
// If subscription is active, ensure minimum balance is maintained
547+
if (params.isActive) {
548+
uint256 minimumBalance = this.getMinimumBalance(
549+
uint8(params.priceIds.length)
550+
);
551+
if (status.balanceInWei < minimumBalance) {
552+
revert InsufficientBalance();
553+
}
554+
}
545555
}
546556

547557
function withdrawFunds(

target_chains/ethereum/contracts/forge-test/PulseScheduler.t.sol

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,134 @@ contract SchedulerTest is Test, SchedulerEvents, PulseSchedulerTestUtils {
541541
"Balance should match initial balance plus added funds"
542542
);
543543
}
544+
545+
546+
547+
function testAddFundsEnforcesMinimumBalance() public {
548+
// First add a subscription with minimum balance
549+
uint256 subscriptionId = addTestSubscription(
550+
scheduler,
551+
address(reader)
552+
);
553+
554+
// Get subscription parameters and initial balance
555+
(SchedulerState.SubscriptionParams memory params, SchedulerState.SubscriptionStatus memory status) = scheduler
556+
.getSubscription(subscriptionId);
557+
558+
// Calculate minimum balance
559+
uint256 minimumBalance = scheduler.getMinimumBalance(
560+
uint8(params.priceIds.length)
561+
);
562+
563+
// Verify initial balance is at minimum
564+
assertEq(
565+
status.balanceInWei,
566+
minimumBalance,
567+
"Initial balance should equal minimum balance"
568+
);
569+
570+
// Add some funds to the subscription
571+
uint256 additionalFunds = 0.1 ether;
572+
scheduler.addFunds{value: additionalFunds}(subscriptionId);
573+
574+
// Verify funds were added
575+
(, SchedulerState.SubscriptionStatus memory statusAfterAdd) = scheduler
576+
.getSubscription(subscriptionId);
577+
assertEq(
578+
statusAfterAdd.balanceInWei,
579+
minimumBalance + additionalFunds,
580+
"Balance should be increased by the added funds"
581+
);
582+
583+
// Now create a new subscription but don't fund it fully
584+
SchedulerState.SubscriptionParams memory newParams = createDefaultSubscriptionParams(
585+
2,
586+
address(reader)
587+
);
588+
589+
// Calculate minimum balance for this new subscription
590+
uint256 newMinimumBalance = scheduler.getMinimumBalance(
591+
uint8(newParams.priceIds.length)
592+
);
593+
594+
// Try to create with insufficient funds
595+
uint256 insufficientFunds = newMinimumBalance - 1 wei;
596+
vm.expectRevert(abi.encodeWithSelector(InsufficientBalance.selector));
597+
scheduler.createSubscription{value: insufficientFunds}(newParams);
598+
599+
// Create with sufficient funds
600+
uint256 newSubscriptionId = scheduler.createSubscription{value: newMinimumBalance}(newParams);
601+
602+
// Verify subscription was created with minimum balance
603+
(, SchedulerState.SubscriptionStatus memory newStatus) = scheduler
604+
.getSubscription(newSubscriptionId);
605+
assertEq(
606+
newStatus.balanceInWei,
607+
newMinimumBalance,
608+
"New subscription balance should equal minimum balance"
609+
);
610+
}
611+
612+
function testAddFundsEnforcesMinimumBalanceForPermanentSubscription() public {
613+
// Create a non-permanent subscription first
614+
uint256 subscriptionId = addTestSubscription(
615+
scheduler,
616+
address(reader)
617+
);
618+
619+
// Get subscription parameters and initial balance
620+
(SchedulerState.SubscriptionParams memory params, SchedulerState.SubscriptionStatus memory status) = scheduler
621+
.getSubscription(subscriptionId);
622+
623+
// Calculate minimum balance
624+
uint256 minimumBalance = scheduler.getMinimumBalance(
625+
uint8(params.priceIds.length)
626+
);
627+
628+
// Verify initial balance is at minimum
629+
assertEq(
630+
status.balanceInWei,
631+
minimumBalance,
632+
"Initial balance should equal minimum balance"
633+
);
634+
635+
// Make it permanent
636+
params.isPermanent = true;
637+
scheduler.updateSubscription(subscriptionId, params);
638+
639+
// Try to add funds - this should succeed since we're adding to a permanent subscription
640+
uint256 additionalFunds = 0.1 ether;
641+
scheduler.addFunds{value: additionalFunds}(subscriptionId);
642+
643+
// Verify funds were added
644+
(, SchedulerState.SubscriptionStatus memory statusAfter) = scheduler
645+
.getSubscription(subscriptionId);
646+
assertEq(
647+
statusAfter.balanceInWei,
648+
minimumBalance + additionalFunds,
649+
"Balance should be increased by the added funds"
650+
);
651+
652+
// Now test the deposit limit for permanent subscriptions
653+
uint256 maxDepositLimit = 100 ether; // MAX_DEPOSIT_LIMIT from SchedulerState
654+
655+
// Try to add funds exceeding the deposit limit
656+
vm.expectRevert(abi.encodeWithSelector(MaxDepositLimitExceeded.selector));
657+
scheduler.addFunds{value: maxDepositLimit + 1}(subscriptionId);
658+
659+
// Add funds within the deposit limit
660+
uint256 validDeposit = 1 ether;
661+
scheduler.addFunds{value: validDeposit}(subscriptionId);
662+
663+
// Verify funds were added
664+
(, SchedulerState.SubscriptionStatus memory statusAfterValidDeposit) = scheduler
665+
.getSubscription(subscriptionId);
666+
assertEq(
667+
statusAfterValidDeposit.balanceInWei,
668+
minimumBalance + additionalFunds + validDeposit,
669+
"Balance should be increased by the valid deposit"
670+
);
671+
}
544672

545673
function testWithdrawFunds() public {
546674
// Add a subscription and get the parameters

0 commit comments

Comments
 (0)