fix(ark): stop auto-board boarding away the exit-fee reserve - #189
CypherBoxLLC wants to merge 1 commit into
Conversation
Auto-board is the only thing that moves the on-chain balance without the user asking, and that balance is where unilateral-exit CPFP fees are paid from. Boarding the wrong amount does not misplace funds, it disarms the exit. Two defects, both in the same block. The hold target was the ARMED reserve only. The estimate of what an exit costs is computed on the exit settings screen and was never persisted, so the sync loop could not see it. A user who funds toward a recommendation far above what they armed would have the difference boarded straight back into Ark, undoing the top-up they made specifically to enable the exit. With the device figures from 2026-08-20, armed 3,654 and an estimate of 233,120, funding to the recommendation left 227,966 sats eligible for boarding, comfortably over the 50,000 minimum, so it would have fired. Nobody has hit this yet because nobody has funded a six-figure reserve. Now that the gate asks for one (#188), somebody will. The unarmed path called boardAll with NO board-minimum guard, while the armed path guarded correctly. A sub-minimum on-chain balance can never board, so it retried every sync tick forever. The old comment acknowledged the asymmetry as "the exact old boardAll behavior". This device has 6,259 sats on-chain against a 50,000 minimum, which is precisely that case. The decision is now a pure function taking the greater of armed and recommended as the hold target, via the same helper the gate uses (#188), so the screen and the sync loop can no longer disagree about what "funded" means. boardAll keeps its original semantics when there is genuinely nothing to hold, so no dust is stranded for users who never touched exit funding, but it is now gated on the minimum like everything else. The estimate is persisted as `arkExitRecommendedReserveSats`, written whenever the settings screen computes it, and cleared by clearArkAuth so a stale figure from a deleted wallet cannot linger. It is derived data: if it is missing, the hold falls back to the armed value, which is the old behaviour. 11 tests using the device figures, mutation-checked: restoring either old behaviour fails 4 of them.
|
Merge note for whoever lands this. Expect a conflict with #179 in
Verified with both resolutions applied: 50 suites, 442 tests green, tsc unchanged. |
|
Landed in This PR did not auto-close because its base was another feature branch rather than Closing as merged. |
Stacked on #188, which it needs for
resolveExitReserveTarget. GitHub will retarget this tomainwhen #188 merges.
Auto-board is the only thing that moves the on-chain balance without the user asking, and that
balance is where unilateral-exit CPFP fees are paid from. Boarding the wrong amount does not misplace
funds, it disarms the exit.
Defect 1: the hold target ignored the estimate
The estimate of what an exit costs is computed on the exit settings screen and was never
persisted, so the sync loop could not see it and held only what the user had armed.
With the device figures from 2026-08-20, armed 3,654 against an estimate of 233,120:
A user who funds to the recommendation by external deposit gets 227,966 sats boarded straight back
into Ark, undoing the top-up they made specifically to enable the exit. Nobody has hit this because
nobody has funded a six-figure reserve. Now that the gate asks for one (#188), somebody will.
Defect 2: the unarmed path had no board-minimum guard
The armed path guards correctly. The unarmed path called
boardAllunconditionally, and asub-minimum balance can never board, so it retried every sync tick forever. The old comment
acknowledged the asymmetry as "the exact old boardAll behavior". This device sits at 6,259 sats
on-chain against a 50,000 minimum, which is exactly that case.
The fix
A pure decision function taking the greater of armed and recommended as the hold target, through
the same helper the gate uses in #188, so the screen and the sync loop can no longer disagree about
what "funded" means.
boardAllkeeps its original semantics when there is genuinely nothing to hold, so no dust isstranded for users who never touched exit funding, but it is now gated on the minimum like everything
else.
The estimate is persisted as
arkExitRecommendedReserveSats, written whenever the settings screencomputes it and cleared by
clearArkAuthso a stale figure from a deleted wallet cannot linger. Itis derived data: if missing, the hold falls back to the armed value, which is the old behaviour.
Verification
tscerror set byte-identical toorigin/main, zero differing lines, none in any touched file