Soroban smart contracts for Vortex Protocol — intent-based cross-chain swaps settled on Stellar.
This repository holds the on-chain logic that guarantees settlement: intent
lifecycle, solver bonds, and slashing. Part of the multi-repo Vortex stack —
see also vortex-backend
and vortex-frontend.
Core protocol logic (intent_settlement/src/lib.rs):
submit_intent()— user creates a swap intentaccept_intent()— solver claims exclusive fill rightsfill_intent()— solver delivers output tokens to the usercancel_intent()— user cancels an open intentexpire_intent()— permissionless: materializes an unfilled intent's expiryslash_solver()— permissionless: slashes a solver that failed to fillregister_solver()/deregister_solver()/withdraw_bond()— solver bond managementset_fee_recipient()/transfer_admin()— admin key managementpause()/unpause()— admin-only incident responseadd_allowed_dst_token()/remove_allowed_dst_token()/set_dst_allowlist_enabled()— optional dst_token allowlist
All examples use the Stellar CLI
against a deployed contract. Swap <CONTRACT_ID> and <SECRET_KEY> for your
deployment; addresses shown are placeholders.
# User submits a swap intent: 1 ETH on Ethereum for at least 3500 USDC on Stellar
stellar contract invoke --id <CONTRACT_ID> --source <SECRET_KEY> --network testnet -- \
submit_intent \
--user <USER_ADDRESS> \
--src_chain '"ethereum"' \
--src_token '"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"' \
--src_amount 1000000000000000000 \
--dst_token <USDC_SAC_ADDRESS> \
--min_dst_amount 35000000000
# Solver registers with a 50 USDC bond (MIN_BOND)
stellar contract invoke --id <CONTRACT_ID> --source <SOLVER_SECRET_KEY> --network testnet -- \
register_solver --solver <SOLVER_ADDRESS> --bond_amount 500000000
# Solver claims exclusive fill rights on an intent
stellar contract invoke --id <CONTRACT_ID> --source <SOLVER_SECRET_KEY> --network testnet -- \
accept_intent --solver <SOLVER_ADDRESS> --intent_id <INTENT_ID>
# Solver delivers the output and closes out the intent
stellar contract invoke --id <CONTRACT_ID> --source <SOLVER_SECRET_KEY> --network testnet -- \
fill_intent --solver <SOLVER_ADDRESS> --intent_id <INTENT_ID> --fill_amount 35000000000
# Anyone can slash a solver that accepted but missed the fill window
stellar contract invoke --id <CONTRACT_ID> --source <ANY_SECRET_KEY> --network testnet -- \
slash_solver --intent_id <INTENT_ID>
# Read-only: check current protocol stats
stellar contract invoke --id <CONTRACT_ID> --source <ANY_SECRET_KEY> --network testnet -- \
get_statsTiered solver staking with reputation scores. See the roadmap below.
- Rust 1.78+ with the
wasm32-unknown-unknowntarget - Stellar CLI
cd intent_settlement
cargo fmt --all
cargo clippy --all-targets -- -D warnings
cargo test
stellar contract buildstellar contract deploy \
--wasm target/wasm32-unknown-unknown/release/vortex_intent_settlement.wasm \
--source <SECRET_KEY> \
--network testnetSettlement relies on two primitives:
- Solver bonds — solvers lock USDC to participate. Failed fills slash 10% of their bond, making repeated failures unprofitable.
- Fill-window enforcement — once a solver accepts, the intent is locked for
5 minutes. If they fail to fill, the intent reverts to
openand is re-auctioned, and the bond is slashed permissionlessly viaslash_solver().
To report a vulnerability, see the org SECURITY.md.
- Contract test suite —
soroban_sdktestutils coverage for the full intent lifecycle, solver bonding/slashing, admin controls, pause, and storage TTL management - Solver registry contract — tiered staking, reputation NFT, dispute resolution
- Cross-chain proof verification — verify source-chain tx on-chain via Stellar oracle / messaging infra
See the org-wide CONTRIBUTING.md.
MIT © 2025–2026 Vortex Protocol Contributors