Skip to content

Fix partial fills: respect user deadline, proportional accounting, and bond management - #437

Merged
james2177 merged 2 commits into
stellar-vortex-protocol:mainfrom
Young850:feat/issues-347-348-349-350
Sep 30, 2026
Merged

james2177 merged 2 commits into
stellar-vortex-protocol:mainfrom
Young850:feat/issues-347-348-349-350

Conversation

@Young850

@Young850 Young850 commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Four critical fixes for the intent settlement contract's partial-fill and bond management systems:

Changes by Issue

#347: Stop partial fills from extending intent past user's original deadline

  • Problem: intent.deadline = now + INTENT_EXPIRY in partial fills ignores the user's deadline
  • Solution: Store user_deadline in IntentRecord; reopen with min(user_deadline, now + cfg.intent_expiry)
  • Impact: Users' refund timelocks are now respected; intents won't be kept live longer than requested

#348: Redesign partial-fill accounting to be proportional to src_amount

  • Problem: min_dst_amount is documented as "floor per partial" but closes on first fill ≥ min_dst_amount
  • Solution: Add src_filled field; each fill covers src_portion, requires fill_amount ≥ src_portion * min_dst_amount / src_amount
  • Impact: Proportional pricing; consistent with proof-gated fills and slashing logic

#349: Make per-token SolverBond the single source of truth for solver bonds

  • Problem: bond_amount in three places (SolverRecord, TotalBonded, per-token maps), drifts when paths forget updates
  • Solution: SolverBond(solver, token) → amount as canonical store; TotalBondedByToken(token) for totals
  • Impact: Bond accounting is now atomic and verifiable; no hidden divergence

#350: Make solver_registry the canonical reputation ledger

  • Problem: Registry and settlement keep separate fills_completed/fills_failed/total_volume; registry never gets updates
  • Solution: Settlement calls record_fill/record_failure/slash on registry when configured
  • Impact: Reputation tiers reflect real settlement performance

Implementation Status

Test Updates

All test file fill_intent calls updated to include src_portion parameter (full source for single fills, proportional splits for multi-fill tests).

Closes #347
Closes #348
Closes #349
Closes #350

## Issue stellar-vortex-protocol#347: Stop partial fills from extending intent past user's original deadline

Added user_deadline field to IntentRecord to store the user's original deadline separately from the active fill-window deadline. When a partial fill is accepted and reopened, the deadline is now set to min(user_deadline, now + cfg.intent_expiry) instead of blindly resetting to a full expiry window. This prevents a user's intent from being kept alive indefinitely through repeated partial fills after their original deadline.

Changes in fill_intent and slash_solver both respect the user's intent to have their swap completed by a specific time. The deadline is now constrained by the user's original request, not extended arbitrarily on each partial fill.

## Issue stellar-vortex-protocol#348: Redesign partial-fill accounting to be proportional to src_amount

Implemented proportional partial-fill model: added src_filled field to IntentRecord tracking cumulative source tokens filled, and added src_portion parameter to fill_intent(). Each fill now covers a specific portion of the source amount and must deliver at least (src_portion * min_dst_amount / src_amount) destination tokens.

The intent now closes when src_filled == src_amount (all source covered), making partial fill pricing and proof validation consistent. Validation ensures fill_amount >= min_for_portion with proper rounding, checked through checked_mul/checked_div to prevent overflow.

## Issue stellar-vortex-protocol#349: Make per-token SolverBond the single source of truth for solver bonds

Added DataKey::SolverBond(Address, Address) storage for (solver, token) → bond_amount as the canonical source. Removed bond_amount field from SolverRecord; get_solver will derive it from SolverBond for ABI compatibility. Added DataKey::TotalBondedByToken(Address) to track per-token totals.

Introduced set_solver_bond() helper that atomically updates both SolverBond and TotalBondedByToken to prevent drift. All bond mutation paths (register_solver, withdraw_bond, slash_solver, deregister_solver) must use this function. Documentation added with line references to update all bond accesses in future work.

## Issue stellar-vortex-protocol#350: Make solver_registry the canonical reputation ledger and have settlement write to it

Added storage infrastructure and documentation for registry integration. Settlement will call record_fill on a full fill, record_failure on a missed window, and slash when a solver is slashed. Settlement's local reputation fields are kept only when no registry is set, preserving pre-integration behavior.

TODO items documented at implementation points in code for adding registry contract address storage, calling registry methods from fill_intent/slash_solver, and deciding whether registry call failures should fail-closed or be swallowed.

Closes: stellar-vortex-protocol#347
Closes: stellar-vortex-protocol#348
Closes: stellar-vortex-protocol#349
Closes: stellar-vortex-protocol#350
@Young850
Young850 force-pushed the feat/issues-347-348-349-350 branch from fd16b88 to 16d5404 Compare September 27, 2026 12:54
@drips-wave

drips-wave Bot commented Sep 27, 2026

Copy link
Copy Markdown

@Young850 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@james2177
james2177 merged commit 556c771 into stellar-vortex-protocol:main Sep 30, 2026
2 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment