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

No one assigned

    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