Skip to content

FLO-28: Safe Refund Ordering Can Brick Config Rotation #237

@liobrasil

Description

@liobrasil

Severity: Low

Files Affected

  • cadence/contracts/FlowALPRebalancerv1.cdc

Description

A natural fix for the “ Refund destination changes after recurring config updates” issue is to change FlowALPRebalancerv1.Rebalancer.setRecurringConfig(_:) so it cancels existing scheduled transactions first (using the old config/old txFunder), and only then assigns self.recurringConfig = config, ensuring refunds go back to the original payer. The intended flow is to allow operators to rotate configuration safely while cleaning up old schedules. In a scenario where the current txFunder has reached its depositCapacity and cannot accept refunds, cancelScheduledTransaction(id:) will panic because refund.balance > 0.0 remains after attempting txFunder.depositCapacity(from:). The normal operational response is to rotate to a new txFunder with higher capacity so cancellations and scheduling can resume. However, if setRecurringConfig is adjusted to call cancelAllScheduledTransactions() before updating self.recurringConfig (as a fix to ensure refunds go back to the original txFunder that paid for the scheduled transactions), this creates a deadlock: the rebalancer cannot cancel existing scheduled transactions due to the refund-capacity panic, so setRecurringConfig cannot complete and therefore cannot install the new, healthy txFunder. This can leave the rebalancer stuck in a state where it cannot be reconfigured, cleanly canceled, or migrated away from the saturated funder.

Recommendation

Make cancellation non-blocking on refund deposit acceptance so config rotation can always proceed even when the old txFunder is saturated. For example: If a refund cannot be fully deposited, store the remainder as a pending refund and emit an event, instead of panicking.


Parent Issue: #209

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions