Skip to content

feat: implement issues #367, #368, #369, #370 - #458

Merged
james2177 merged 3 commits into
stellar-vortex-protocol:mainfrom
kurehkim334-lang:feature/issues-367-368-369-370
Oct 2, 2026
Merged

james2177 merged 3 commits into
stellar-vortex-protocol:mainfrom
kurehkim334-lang:feature/issues-367-368-369-370

Conversation

@kurehkim334-lang

Copy link
Copy Markdown
Contributor

#367 - Exposure-weighted bonding

  • Add accepted_notional exposure tracking to SolverRecord via DataKey::SolverExposure(Address)
  • Add ExposureExceeded error (code 68)
  • accept_intent: compute notional at 1.0x weight (oracle-ready), check new_exposure <= bond * coverage_multiplier, persist to SolverExposure
  • fill_intent: release exposure on fill (full notional on complete fill, proportional on partial)
  • slash_solver: release unfilled notional on slash
  • Add get_solver_exposure(solver) -> (used, capacity) view
  • Add coverage_multiplier field to ProtocolConfig (default 10x)

#368 - Oracle adapter

  • New intent_settlement/src/oracle.rs module with SEP-40-compatible OracleAdapterClient interface (lastprice -> Option)
  • Staleness guard (MAX_PRICE_AGE_SECS = 300s) and deviation guard (MAX_PRICE_DEVIATION_BPS = 200bps) with fail-closed OracleFault enum
  • Timelocked admin setter: propose_oracle / execute_oracle (48h delay)
  • get_oracle() view; DataKey::OracleAddr + PendingOracle
  • Error variants: OraclePriceStale, OraclePriceInvalid, OracleNotConfigured, OracleTimelockNotElapsed, NoPendingOracle

#369 - Harden claim_backstop_compensation

  • Eligible states: Slashed OR (Open/PartiallyFilled with slash_cycles > 0)
  • Per-intent cap: MAX_BACKSTOP_INTENT_BPS (10%) of min_dst_amount
  • Per-user epoch cap: MAX_BACKSTOP_USER_EPOCH_CLAIM per 24h epoch via DataKey::UserEpochClaim(Address, u64)
  • Pro-rata when pool is short: payout = min(intent_cap, epoch_remaining, pool)
  • Idempotent double-claim guard via BackstopClaimed key
  • Add slash_cycles: u32 field to IntentRecord (incremented in slash_solver)
  • Collusion analysis: docs/369-backstop-collusion-analysis.md

#370 - Backstop LP vault

  • New backstop_vault/ crate (vortex-backstop-vault)
  • deposit/withdraw with 48h cooldown (deposit-delay front-run protection)
  • Virtual shares/assets seed at init for inflation-attack resistance
  • cover(intent_id, amount, recipient): settlement-only, loss socialized
  • receive_income(amount): routes fee/slash share, increases TotalAssets
  • Emergency withdrawal-queue mode (set_emergency_mode + process_queued_withdrawal)
  • get_vault_state() and get_lp_position() views
  • DataKey::BackstopVault + BackstopVaultShareBps in intent_settlement
  • backstop_vault_share_bps in ProtocolConfig; slash_solver routes vault share to DataKey::BackstopPool when configured

Also fixes all pre-existing compilation errors:

  • Remove 14 duplicate const declarations (DISPUTE_WINDOW, ARBITER_WINDOW, SLASH_COOLDOWN, CANCEL_COOLDOWN, MAX_BATCH_SIZE, MAX_EXTENSION_DURATION, DEFAULT_MIN_BOND, DEFAULT_FILL_WINDOW, DEFAULT_INTENT_EXPIRY, DEFAULT_PROTOCOL_FEE_BPS, MAX_PROTOCOL_FEE_BPS, MIN_FILL_WINDOW_SECS, MIN_INTENT_EXPIRY_SECS, MIN_BOND_FLOOR)
  • Add 31 missing DataKey variants (SolverBond, AllowedBondToken, MinBond, SolverIntents, TotalBonded, TokenVolume, TokenFees, FeeDiscountTiers, OpenIntentList, SolverRegistry, SolverRoutes, SolverReputation, PendingUpgrade, MigrationVersion, BidWindowEnabled, BestBid, Arbiter, BackstopPool, BackstopClaimed, SolverExposure, OracleAddr, PendingOracle, UserEpochClaim, BackstopVault, BackstopVaultShareBps, and others)
  • Add 31 missing Error variants (InvalidConfig, TimelockNotElapsed, NoPendingAdminTransfer, NoPendingDstTokenChange, CancelCooldownNotExpired, AmountTooLarge, ImplausibleDstAmount, MaxActiveIntentsCapReached, BondTokenNotAllowed, ExtensionAlreadyGranted, AlreadyMigrated, BidWindowClosed, BidWindowStillOpen, BidNotHigher, IntentNotBidding, IntentNotFilling, IntentNotDisputed, NotArbiter, ArbiterWindowExpired, DisputeWindowStillOpen, DisputeWindowExpired, DisputeWindowClosed, NoFillEscrowed, NoPendingUpgrade, IntentNotAcceptedForFill, TooManyBondTokens, TooManyRouteEntries, BatchTooLarge, NoDisputeOpen, BackstopPoolEmpty, BackstopAlreadyClaimed, ExposureExceeded)
  • Add referrer: Option and slash_cycles: u32 to IntentRecord
  • Add max_slash_cycles, referral_share_bps, backstop_vault_share_bps, coverage_multiplier to ProtocolConfig
  • Add missing constants: DEFAULT_MAX_ACTIVE_INTENTS_PER_SOLVER, BID_WINDOW, MAX_BACKSTOP_INTENT_BPS, MAX_BACKSTOP_USER_EPOCH_CLAIM, BACKSTOP_EPOCH_SECS, MAX_WHOLE_UNITS, MAX_REFERRAL_SHARE_BPS, MAX_FILL_HISTORY, etc.
  • Fix duplicate accept_intent_inner: rename inner body to accept_intent_inner_body
  • Fix fill_intent_inner: remove duplicate premature token transfer and duplicate fee calculation; add require_proof parameter
  • Fix slash_solver: replace undefined fee_recipient_share/caller_rebate/caller variables with proper vault-routing logic
  • Fix set_config: remove stale referral_share_bps guard using undefined var

Updates .gitignore: backstop_vault/target/, coverage artifacts (lcov.info, coverage/, tarpaulin-report.html), profiling artifacts (*.profdata, *.profraw), backstop_vault/Cargo.lock

Summary

Related issue

Type of change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI / tooling

Component

  • Contract (vortex-contract)
  • Backend (vortex-backend)
  • Frontend (vortex-frontend)

Checklist

  • My code follows the project's style and conventions
  • I ran lint / type-check / build locally and they pass
  • I added or updated tests where appropriate
  • I updated documentation where appropriate
  • My commits follow Conventional Commits

Screenshots / notes

CLOSES
closes #367
closes #368
closes #369
closes #370

…otocol#368, stellar-vortex-protocol#369, stellar-vortex-protocol#370

stellar-vortex-protocol#367 - Exposure-weighted bonding
- Add `accepted_notional` exposure tracking to SolverRecord via
  DataKey::SolverExposure(Address)
- Add ExposureExceeded error (code 68)
- accept_intent: compute notional at 1.0x weight (oracle-ready), check
  new_exposure <= bond * coverage_multiplier, persist to SolverExposure
- fill_intent: release exposure on fill (full notional on complete fill,
  proportional on partial)
- slash_solver: release unfilled notional on slash
- Add get_solver_exposure(solver) -> (used, capacity) view
- Add coverage_multiplier field to ProtocolConfig (default 10x)

stellar-vortex-protocol#368 - Oracle adapter
- New intent_settlement/src/oracle.rs module with SEP-40-compatible
  OracleAdapterClient interface (lastprice -> Option<PriceData>)
- Staleness guard (MAX_PRICE_AGE_SECS = 300s) and deviation guard
  (MAX_PRICE_DEVIATION_BPS = 200bps) with fail-closed OracleFault enum
- Timelocked admin setter: propose_oracle / execute_oracle (48h delay)
- get_oracle() view; DataKey::OracleAddr + PendingOracle
- Error variants: OraclePriceStale, OraclePriceInvalid, OracleNotConfigured,
  OracleTimelockNotElapsed, NoPendingOracle

stellar-vortex-protocol#369 - Harden claim_backstop_compensation
- Eligible states: Slashed OR (Open/PartiallyFilled with slash_cycles > 0)
- Per-intent cap: MAX_BACKSTOP_INTENT_BPS (10%) of min_dst_amount
- Per-user epoch cap: MAX_BACKSTOP_USER_EPOCH_CLAIM per 24h epoch
  via DataKey::UserEpochClaim(Address, u64)
- Pro-rata when pool is short: payout = min(intent_cap, epoch_remaining, pool)
- Idempotent double-claim guard via BackstopClaimed key
- Add slash_cycles: u32 field to IntentRecord (incremented in slash_solver)
- Collusion analysis: docs/369-backstop-collusion-analysis.md

stellar-vortex-protocol#370 - Backstop LP vault
- New backstop_vault/ crate (vortex-backstop-vault)
- deposit/withdraw with 48h cooldown (deposit-delay front-run protection)
- Virtual shares/assets seed at init for inflation-attack resistance
- cover(intent_id, amount, recipient): settlement-only, loss socialized
- receive_income(amount): routes fee/slash share, increases TotalAssets
- Emergency withdrawal-queue mode (set_emergency_mode + process_queued_withdrawal)
- get_vault_state() and get_lp_position() views
- DataKey::BackstopVault + BackstopVaultShareBps in intent_settlement
- backstop_vault_share_bps in ProtocolConfig; slash_solver routes vault share
  to DataKey::BackstopPool when configured

Also fixes all pre-existing compilation errors:
- Remove 14 duplicate const declarations (DISPUTE_WINDOW, ARBITER_WINDOW,
  SLASH_COOLDOWN, CANCEL_COOLDOWN, MAX_BATCH_SIZE, MAX_EXTENSION_DURATION,
  DEFAULT_MIN_BOND, DEFAULT_FILL_WINDOW, DEFAULT_INTENT_EXPIRY,
  DEFAULT_PROTOCOL_FEE_BPS, MAX_PROTOCOL_FEE_BPS, MIN_FILL_WINDOW_SECS,
  MIN_INTENT_EXPIRY_SECS, MIN_BOND_FLOOR)
- Add 31 missing DataKey variants (SolverBond, AllowedBondToken, MinBond,
  SolverIntents, TotalBonded, TokenVolume, TokenFees, FeeDiscountTiers,
  OpenIntentList, SolverRegistry, SolverRoutes, SolverReputation,
  PendingUpgrade, MigrationVersion, BidWindowEnabled, BestBid, Arbiter,
  BackstopPool, BackstopClaimed, SolverExposure, OracleAddr, PendingOracle,
  UserEpochClaim, BackstopVault, BackstopVaultShareBps, and others)
- Add 31 missing Error variants (InvalidConfig, TimelockNotElapsed,
  NoPendingAdminTransfer, NoPendingDstTokenChange, CancelCooldownNotExpired,
  AmountTooLarge, ImplausibleDstAmount, MaxActiveIntentsCapReached,
  BondTokenNotAllowed, ExtensionAlreadyGranted, AlreadyMigrated,
  BidWindowClosed, BidWindowStillOpen, BidNotHigher, IntentNotBidding,
  IntentNotFilling, IntentNotDisputed, NotArbiter, ArbiterWindowExpired,
  DisputeWindowStillOpen, DisputeWindowExpired, DisputeWindowClosed,
  NoFillEscrowed, NoPendingUpgrade, IntentNotAcceptedForFill,
  TooManyBondTokens, TooManyRouteEntries, BatchTooLarge, NoDisputeOpen,
  BackstopPoolEmpty, BackstopAlreadyClaimed, ExposureExceeded)
- Add referrer: Option<Address> and slash_cycles: u32 to IntentRecord
- Add max_slash_cycles, referral_share_bps, backstop_vault_share_bps,
  coverage_multiplier to ProtocolConfig
- Add missing constants: DEFAULT_MAX_ACTIVE_INTENTS_PER_SOLVER, BID_WINDOW,
  MAX_BACKSTOP_INTENT_BPS, MAX_BACKSTOP_USER_EPOCH_CLAIM, BACKSTOP_EPOCH_SECS,
  MAX_WHOLE_UNITS, MAX_REFERRAL_SHARE_BPS, MAX_FILL_HISTORY, etc.
- Fix duplicate accept_intent_inner: rename inner body to accept_intent_inner_body
- Fix fill_intent_inner: remove duplicate premature token transfer and
  duplicate fee calculation; add require_proof parameter
- Fix slash_solver: replace undefined fee_recipient_share/caller_rebate/caller
  variables with proper vault-routing logic
- Fix set_config: remove stale referral_share_bps guard using undefined var

Updates .gitignore: backstop_vault/target/, coverage artifacts (lcov.info,
coverage/, tarpaulin-report.html), profiling artifacts (*.profdata, *.profraw),
backstop_vault/Cargo.lock
@drips-wave

drips-wave Bot commented Sep 30, 2026

Copy link
Copy Markdown

@kurehkim334-lang 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 3999a3a into stellar-vortex-protocol:main Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants