The shortest path between Stellar and every other chain.
An open-source, intent-based cross-chain bridge connecting Stellar to EVM-compatible networks — Ethereum, Base, Arbitrum, and beyond.
Overview · Why Perihelion · How It Works · Architecture · Getting Started · Documentation · Contributing · FAQ
- Overview
- Why Perihelion
- Features
- How It Works
- Architecture
- Repository Layout
- Tech Stack
- Getting Started
- How Perihelion Compares
- Documentation
- Roadmap
- Project Status
- Contributing
- Trust Assumptions
- Security
- Community & Support
- License
- Acknowledgements
Perihelion lets a user declare a simple intent — "I want X amount of asset Y on Stellar" — and a decentralized network of solvers competes to fulfill it, atomically and at the best available rate. No manual bridging steps, no token wrapping, no fragile multi-transaction dance.
It is built natively on Soroban, Stellar's smart contract platform, and is designed for the way Stellar actually works: fast finality, low fees, and a growing ecosystem of real-world assets that need seamless liquidity connections to the rest of the blockchain world.
The model is proven on Ethereum — it is the same architecture behind UniswapX and CoW Protocol — but it has been largely absent from Stellar. Perihelion brings it to Soroban and uses it to solve Stellar's single most important growth bottleneck: inbound liquidity.
Stellar has become critical financial infrastructure — over $2B in tokenized real-world assets, institutional-grade stablecoins (USDC, EURC, YLDS, MGUSD), and payment rails used by MoneyGram, Franklin Templeton, and PayPal.
But moving assets onto Stellar from Ethereum, Base, or any other major chain still requires one of:
- Centralized exchanges — custodial, KYC-gated, slow withdrawals.
- Manual DEX hops — multiple transactions, MEV exposure, poor rates.
- Lock-and-mint bridges — custodial wrapper assets and a long history of catastrophic exploits.
Capital that should be flowing into Stellar's DeFi, lending markets, and RWA platforms sits on other chains because the on-ramp is too hard.
Perihelion replaces all of that with a single signed message. The user never touches a wrapper asset, never executes a multi-step bridge, and never takes custodial risk. Either they receive at least the amount they asked for on Stellar, or they are refunded in full on the source chain. There is no state in which a user loses funds mid-bridge.
- 🎯 Intent-based UX — users sign what they want, not how to get it.
- ⚡ Atomic settlement — fill both legs or refund; no partial states.
- 🤝 Solver competition — an open network races to give users the best rate, instead of a single privileged operator.
- 🔓 Permissionless — anyone can run a solver, a relayer, or a keeper. No allowlist gates liveness, and the refund path needs no privileged actor.
- 🛰️ LayerZero-secured messaging — verified cross-chain delivery with a multi-DVN trust model, plus a roadmap to ZK state proofs (Protocol 24).
- 🪙 Canonical assets — users receive real Stellar assets sourced from solver liquidity, never a synthetic wrapper.
- 🧱 Built for contributors — a clean monorepo with scoped, skill-tagged issues for Drips Wave sprint cycles.
Perihelion uses an intent + solver architecture:
- The user declares an intent. They sign a structured message off-chain specifying the asset and amount to receive on Stellar, the asset and chain to spend from, a deadline, and a slippage floor. No transaction, no gas yet.
- Solvers compete to fill it. A decentralized network of solvers monitors the intent mempool and races to fill profitable orders. The winner earns the spread between what the user offered and what the solver sourced.
- Atomic settlement. The user's funds are locked in the source-chain escrow against a cryptographic commitment; the solver fronts liquidity on Stellar; the escrow releases the locked funds to the solver once settlement is verified over LayerZero. If the deadline passes without a fill, the user is refunded.
- Trust-minimized messaging. Cross-chain messages are carried by LayerZero with an independent multi-DVN verifier set, and — on the roadmap — Stellar's native ZK proof support (Protocol 24) for the most sensitive path.
User Intent (signed off-chain)
│
▼
Intent Mempool (open, permissionless)
│
├──► Solver A evaluates
├──► Solver B evaluates
└──► Solver C evaluates
│
▼
Winning Solver executes
│
┌──────────┴──────────┐
▼ ▼
Source Chain Escrow Soroban Settlement
(EVM Contract) Contract (Stellar)
│ │
└──── LayerZero ──────┘
Message Relay
│
▼
User receives assets
on Stellar ✓
A single value — the EIP-712 intent_hash — ties every leg together. It is:
- the commitment the EVM escrow locks the user's funds against,
- the identifier carried in every LayerZero message,
- and the key the Soroban settlement contract uses for replay protection.
The hash is computed identically by the SDK (hashIntent) and the EVM escrow
(hashIntent), so every component keys off one stable identifier. The full
design — storage layout, state machine, message formats, threat model, and
phased rollout — is in the
Technical Architecture Specification.
| Path | Description |
|---|---|
contracts/ |
Soroban (Rust) settlement contract + EVM (Solidity) escrow contract |
sdk/ |
TypeScript SDK for intent construction, signing, and submission |
solver/ |
Reference solver node — monitors the mempool and fills intents |
relayer/ |
LayerZero message relayer for the Stellar ↔ EVM path |
docs/ |
Protocol specifications and integration guides |
This is an npm workspaces
monorepo for the TypeScript packages (sdk, solver, relayer), a Cargo
workspace for the Soroban contracts, and a Foundry project for the EVM contracts.
| Layer | Technology |
|---|---|
| Stellar smart contracts | Rust / Soroban (SDK 22) |
| EVM contracts | Solidity 0.8.24 / Foundry |
| Cross-chain messaging | LayerZero V2 |
| ZK verification | BN254 / Stellar Protocol 24 |
| Oracle pricing | SEP-40 / RedStone |
| Solver, SDK, relayer | TypeScript / Node.js ≥ 20 |
| Intent standard | EIP-712 style signed messages |
New here? Jump straight to the Integration Quickstart for a copy-pasteable, end-to-end walkthrough: install → build intent → sign → submit → track settlement against a local mock mempool.
| Tool | Used for | Required version |
|---|---|---|
| Node.js | SDK, solver, relayer | ≥ 20 |
Rust + wasm32-unknown-unknown target |
Soroban contracts | stable |
| Stellar CLI | Soroban build/deploy | latest |
| Foundry | EVM contracts | latest |
The TypeScript packages build and test with only Node.js installed; the Rust and Foundry toolchains are needed solely for the contracts.
# Clone
git clone https://github.com/Perihelion-Protocol/Perihelion.git
cd Perihelion
# 1. TypeScript workspaces (sdk, solver, relayer)
npm install
npm run build
# 2. Soroban settlement contract
cd contracts/soroban
cargo build --target wasm32-unknown-unknown --release
cd ../..
# 3. EVM escrow contract
cd contracts/evm
forge install foundry-rs/forge-std # one-time
forge build
cd ../..npm test # all TypeScript packages
( cd contracts/soroban && cargo test ) # Soroban unit tests
( cd contracts/evm && forge test ) # EVM unit tests
# Differential fuzzing for wire format codecs
make fuzz-bounded # 100 cases (~30s)
make fuzz-extended # 10k cases (~5min)import { PerihelionClient, buildIntent } from "@perihelion/sdk";
const client = new PerihelionClient({ mempoolUrl: "https://mempool.perihelion.xyz" });
const intent = buildIntent({
user: account.address,
destination: "GUSER...STELLAR",
sourceChainId: 8453, // Base
sourceAsset: "0x833589...", // USDC on Base
sourceAmount: "1000000", // 1 USDC (6 decimals)
destAsset: "USDC:GA5Z...", // USDC on Stellar
minDestAmount: "9900000", // accept >= 0.99 (7 decimals)
deadline: Math.floor(Date.now() / 1000) + 600,
});
const signed = await client.signIntent(wallet, intent); // viem WalletClient
const hash = await client.submitIntent(signed);
const result = await client.waitForSettlement(hash);
console.log(result.status); // "settled"See the sdk/ README for the full API.
| Property | Centralized exchange | Lock-and-mint bridge | Perihelion |
|---|---|---|---|
| Custody during transfer | Custodial | Custodial (wrapper) | Non-custodial |
| Asset received | Native | Synthetic wrapper | Canonical Stellar |
| Steps for the user | Many (KYC, withdraw) | Multiple txs | One signature |
| Worst-case for the user | Frozen funds | Wrapper depeg / hack | Refund in full |
| Rate discovery | Order book | Fixed / oracle | Open solver auction |
| Operator trust | Full | Bridge multisig | DVN set + (ZK roadmap) |
| Document | Description |
|---|---|
| Integration Quickstart | Copy-pasteable end-to-end walkthrough: install → sign → submit → settle |
| Technical Architecture | Full production spec: contracts, LayerZero V2, solver economics, security, testing, rollout |
| Intent Lifecycle Diagram | Canonical state diagram mapping SDK / EVM / Soroban vocabularies, all transitions and terminal paths |
| Architecture Overview | High-level settlement flow and trust model |
| Intent Specification | The signable intent format and EIP-712 encoding |
| Deployment & Operations | Production deployment, the timelock-multisig owner + guardian, and admin/incident runbooks |
| Relayer Runbook | Relayer operator guide: key management, configuration, monitoring, crash recovery, reorg handling, and incident playbooks |
| Solver Runbook | Solver operator guide: setup, configuration, monitoring, and troubleshooting |
| Differential Fuzzing | Wire format codec validation harness for detecting encoder/decoder divergence |
| Coverage Reporting | How to produce and interpret lcov/Codecov coverage for all three languages |
| Glossary | Definitions of every protocol term |
| FAQ | Common questions about safety, solvers, and trust |
| Contributing Guide | How to contribute and where the work lives |
| Component READMEs | contracts · sdk · solver · relayer |
| Phase | Focus | Trust model |
|---|---|---|
| Phase 1 | Guarded mainnet-beta: one corridor, allowlisted solvers, value caps | DVN set + team multisig (timelocked) |
| Phase 2 | Multi-route, permissionless solvers & relayers | DVN set only (no per-operator trust) |
| Phase 3 | ZK state-proof verification (BN254 / Protocol 24), on-chain governance | Proof-system soundness |
Each phase has measurable acceptance criteria and an external audit gate before the next begins. See the phased rollout for details.
Perihelion is in active early development. Current focus: the Soroban settlement contract and the intent specification.
⚠️ The interfaces and on-chain formats described here are not yet stable, are unaudited, and may change before the first audited release. Do not use in production.
We build in public and welcome contributors at every stage — from architecture discussions to the first lines of contract code.
Status of each component as of HEAD. Rows are written against the code, not
against the roadmap: read a row as a claim about what the code does today. CI
fails if a row here links to a closed issue (scripts/check-status-links.mjs).
| Component | Status | Details |
|---|---|---|
| LayerZero Endpoint (Soroban) | Interface + Mock | contracts/soroban/settlement/src/endpoint.rs defines the LzEndpoint trait as a minimal, swappable abstraction. During this phase, a mock contract implements this surface; the real endpoint (or a thin adapter) will implement the same signature once the Soroban LayerZero stack is GA. The Soroban side does not yet communicate with a live LayerZero endpoint. |
| Inbound FillInstruction Codec | Implemented, wire format under revision | messages.rs decodes FillInstruction, CancelIntent, and confirmation payloads from LayerZero bytes. The wire format is not frozen: field widths and address encoding are still being revised, so a decoder built against it today may need updating. |
| Relayer EVM Watcher | Implemented | relayer/src/evm-watcher.ts polls source-chain logs through viem with bounded block ranges and concurrent transaction fetches. |
| Relayer Soroban Delivery | Implemented, archived-entry restore incomplete | relayer/src/soroban-delivery.ts builds, simulates, and submits lz_receive calls against the settlement contract. Archived ledger entries are detected but the RestoreFootprint operation is not yet constructed from the simulation footprint, so delivery to an archived contract still fails. Tracked by the TODO(#303) in that file; #303 is closed, no successor filed yet. |
| Solver Executor | Stub | solver/src/executor.ts implements the orchestration flow, but lockOnEvm, fillOnSoroban, and isSettled all throw Executor not implemented. No solver can execute an intent end to end. |
| Value Caps / Circuit Breaker | Implemented (rolling window only) | Rolling-window value caps and a latching breaker exist on both chains: PerihelionEscrow.sol (rollingWindowCap, rollingWindowTriggered, resetRollingWindow) and lib.rs (set_rolling_window_cap, reset_rolling_window_cap). Once tripped, the breaker stays tripped until an admin resets it. There is still no per-intent maximum lock: a single intent of any size passes as long as the window cap is not exceeded. |
| SDK Deployment Addresses | Placeholder | sdk/src/deployments.ts ships placeholder addresses. The SDK cannot target a live deployment until they are filled in. |
This section is maintained as features land, and a PR that changes a component's status is expected to update the affected row. For an exhaustive implementation roadmap, see the phased rollout section of the Technical Architecture.
Contributions are welcome at every level. The project is structured around clearly scoped, skill-tagged issues designed for Drips Wave sprint cycles, across four tracks: Rust/Soroban, Solidity, TypeScript, and Documentation.
- Read the Contributing Guide and the Code of Conduct.
- Browse the issue taxonomy to find work matched to your skills and a Wave cycle.
- Open or claim an issue, branch, implement with tests, and open a PR.
All PRs run through CI (npm test, cargo test, forge test) and are reviewed
against the protocol's design invariants.
The claims above ("no custodial risk," "never lose funds mid-bridge") describe the normal intent flow: while a lock is in transit, the protocol's invariants (I1–I5, see Architecture) guarantee a user is either settled or refunded. They do not describe the governance layer. Scoped honestly, per role:
| Role | Can do | Cannot do | Bounding mechanism |
|---|---|---|---|
| Solver / Relayer / Keeper | Delay or decline to act | Steal funds, forge a fill, censor permanently (anyone can take over) | Permissionless; wire-format and signature checks |
| LayerZero DVN set | — | — | Root of message authenticity; a colluding DVN set can forge a fill (see T16) |
| Guardian (EVM) | Pause new locks and local refunds, for up to 72h per 144h cycle | Move funds, change config, unpause | Auto-expiry + cooldown (T11) |
| EVM timelock owner set | Rotate the peer, guardian, or grace period; withdraw any token balance the escrow holds via skim, with no on-chain bound relating it to locked funds |
Bypass the timelock delay for peer/grace/guardian changes | M-of-N confirmation + public delay for config changes; skim itself has no delay, no cap, and no per-token accounting (T17) |
| A single EVM timelock owner | Cancel any pending operation, including a legitimate unpause or guardian rotation | Execute an operation alone | None at present — this is a liveness single point of failure (T20) |
| Soroban admin | Rotate the LayerZero endpoint instantly, with no delay | — | propose_peer/confirm_peer have a 1-day delay; set_endpoint does not (T18) |
The practical implication: the escrow's custody guarantee is only as strong
as the timelock owner set's honesty, because skim is unbounded and the
refund path (cancelExpired) is itself pausable. This is the single largest
concentration of risk in the protocol today and is not yet mitigated on-chain
— see docs/threat-model.md §0 and T17–T20 for the
full trust model, likelihood/impact assessment, and tracked mitigation issues.
Perihelion is unaudited and under active development. If you discover a
vulnerability, please do not open a public issue — follow the responsible
disclosure process in SECURITY.md.
- 🐛 Bugs & features: open an issue
- 💬 Questions & design discussion: GitHub Discussions
- 📣 Updates: watch the repository for releases
Licensed under the MIT License.
Built on the shoulders of the Stellar Development Foundation, Soroban, and LayerZero, and inspired by the intent-based designs pioneered by UniswapX and CoW Protocol.
Perihelion — named for the point of closest approach between two orbiting bodies. The shortest, most efficient path between Stellar and the rest of the blockchain universe.