Skip to content

fix: prevent closePosition panic when withdrawals map is empty#195

Open
liobrasil wants to merge 1 commit intov0from
lionel/fix-close-position-empty-vaults-panic
Open

fix: prevent closePosition panic when withdrawals map is empty#195
liobrasil wants to merge 1 commit intov0from
lionel/fix-close-position-empty-vaults-panic

Conversation

@liobrasil
Copy link
Contributor

@liobrasil liobrasil commented Mar 4, 2026

Summary

This PR fixes an edge-case panic in closePosition when the position has no debt and no remaining collateral at close time.

Real panic scenario (before this fix)

  1. User opens a position and deposits 100.0 FLOW.
  2. User never borrows.
  3. User withdraws the full 100.0 FLOW.
  4. User calls repay_and_close_position.cdc to close.

At this point in closePosition:

  • debtsByType = {} (no debt to repay),
  • collateralTypes = [],
  • _withdrawAllCollateral(...) returns vaults = [].

The old code then built withdrawalsByType with:

  • for i in InclusiveRange(0, vaults.length - 1)

With vaults.length == 0, this range evaluates to InclusiveRange(0, -1) (which iterates 0, -1).
The first iteration tries vaults[0] on an empty array, causing an out-of-bounds runtime panic and reverting close.

Root cause

Using an index-based loop that assumes a non-empty array when building withdrawalsByType.

Fix

In FlowALPv0.cdc close flow, replaced the inclusive-range index loop with a bounds-safe loop:

  • var i = 0
  • while i < vaults.length { ...; i = i + 1 }

This preserves behavior for non-empty arrays and safely no-ops for empty arrays.

Why this is safe

  • No change to close business logic.
  • No change to debt repayment semantics.
  • No API changes.
  • Change is localized to event-map construction (withdrawalsByType) and only affects iteration safety.

Tests

Added regression test:

  • cadence/tests/close_position_empty_position_test.cdc

The test executes the real scenario above and asserts close succeeds without panic and funds are returned as expected.

Also re-ran existing close-related tests to ensure no regressions:

  • close_position_dust_return_test.cdc
  • close_position_precision_test.cdc
  • close_position_queued_overpayment_test.cdc
  • close_position_rounding_overpayment_test.cdc

Risk / Compatibility

  • Low risk.
  • Backward compatible.
  • Prevents a production-blocking close failure for valid no-debt / fully-withdrawn positions.

@liobrasil liobrasil requested a review from a team as a code owner March 4, 2026 19:37
@liobrasil liobrasil mentioned this pull request Mar 4, 2026
6 tasks
Base automatically changed from nialexsan/close-position to v0 March 5, 2026 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant