Skip to content
dandel6Public

About

하이브리드 무기한 선물 DEX. 오프체인 Rust 매칭 엔진, 온체인 정산은 Arbitrum Sepolia. Solidity/Foundry, Pyth 오라클, EIP-712 주문. 테스트넷 전용

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

16 Commits

Folders and files

Repository files navigation

Perp DEX

English | 한국어

A hybrid perpetual futures exchange: orders are matched off-chain by a Rust engine, then settled on-chain in batches on Arbitrum Sepolia. Users sign EIP-712 orders, the contracts verify every signature and re-check margin, so the operator can sequence trades but cannot forge them.

Live demo: coming back soon · Contracts: Arbitrum Sepolia

Architecture

flowchart LR
    subgraph client [Client]
        WEB[React app<br/>wagmi + viem]
    end

    subgraph offchain [Off-chain, Rust]
        API[api server<br/>axum, REST + WS]
        ENGINE[matching-engine<br/>price-time priority]
        RELAYER[settlement relayer]
        MIRROR[mirror bot]
    end

    subgraph onchain [Arbitrum Sepolia]
        CH[ClearingHouse]
        VAULT[USDCMarginVault]
        ORACLE[OracleAdapter]
        FUND[FundingEngine]
    end

    PYTH[Pyth Hermes]
    BIN[Binance feeds]

    WEB -- "EIP-712 signed orders" --> API
    WEB -- "deposit / faucet" --> VAULT
    BIN --> MIRROR
    MIRROR -- "liquidity quotes" --> API
    API --> ENGINE
    ENGINE -- "fills" --> RELAYER
    RELAYER -- "submitFillBatch + Pyth VAA" --> CH
    PYTH --> API
    CH --> ORACLE
    CH --> VAULT
    CH --> FUND
Loading

Order lifecycle: the browser signs an EIP-712 order and POSTs it to the API. The matching engine (strict price-time priority, integer-only math) produces fills at the maker's resting price. The relayer batches fills per market, attaches a fresh Pyth price update, and calls ClearingHouse.submitFillBatch. The contract verifies both signatures on every fill, checks the fill against a ±1% oracle price band, applies funding, updates positions, and finally requires every touched account to still have non-negative free collateral. Any violation reverts the whole batch.

More detail in docs/architecture.md.

Why hybrid

Fully on-chain order books are expensive and slow; fully off-chain exchanges ask you to trust the operator with custody. This project splits the difference:

  • Off-chain: order intake, the book, and matching. Sub-millisecond, free to cancel-and-replace, no gas per order.
  • On-chain: custody (USDC vault), settlement, and risk checks. The ClearingHouse never trusts the matcher: it recovers both EIP-712 signatures, enforces the maker-price rule, bounds fills to an oracle band, and re-derives margin before accepting a batch.

The failure mode this buys: a malicious or buggy operator can censor or reorder trades, but cannot invent a fill you never signed, fill you at a price outside the band, or touch collateral beyond what settled fills justify. Withdrawal requests bump an on-chain nonce that invalidates outstanding signed orders.

The tradeoffs are documented honestly in docs/design-decisions.md and docs/known-limitations.md.

Repo layout

contracts/        Foundry project: ClearingHouse, vault, funding, oracle adapter, waterfall
services/         Rust workspace
  matching-engine   order book + numeric core (no deps, no floats, no unsafe)
  api               axum server: REST/WS, Pyth + Binance feeds, relayer, demo ledger
  mirror            Binance depth mirroring bot (testnet liquidity)
  oracle, vault-quote-engine, liquidator   designed + unit-tested, not yet wired in
apps/web/         React trading UI (chart, book, order form, positions, faucet)
webtestnet/       separate read-only ops dashboard prototype

Running locally

Prerequisites: Rust 1.91 (pinned via rust-toolchain.toml), Foundry, Node 22 + pnpm.

API server (demo mode, no chain access needed):

cd services
DEMO_MODE=true cargo run -p api        # listens on :3001

Frontend:

cd apps/web
pnpm install
pnpm dev                               # http://localhost:5173, talks to :3001 by default

Optional liquidity bot, mirrors Binance depth into the book:

cd services
cargo run -p mirror                    # API_URL defaults to http://localhost:3001

Contracts:

cd contracts
forge test
forge script script/Deploy.s.sol --rpc-url $ARBITRUM_SEPOLIA_RPC --broadcast   # needs DEPLOYER_KEY

Environment variables the API understands: API_PORT (default 3001), DEMO_MODE (off-chain position ledger + liquidation loop), RELAYER_KEY + ARBITRUM_SEPOLIA_RPC (both set = relayer submits batches on-chain, otherwise it logs what it would send), PYTH_HERMES_URL, LOSS_VAULT_BPS / LOSS_PROTOCOL_BPS / LOSS_INSURANCE_BPS. Frontend: VITE_API_URL, VITE_WS_URL.

Tech stack

  • Contracts: Solidity 0.8.24, Foundry, via_ir. No forge-std, no OpenZeppelin: every interface and test harness is vendored here, so the whole trust surface is in this repo.
  • Services: Rust 1.91, axum, tokio, alloy (EIP-712 + contract calls), tokio-tungstenite. The matching engine crate has zero dependencies, forbids unsafe code, and denies float arithmetic.
  • Frontend: React 18, Vite, TypeScript, wagmi v2 + viem, TradingView lightweight-charts, Tailwind.
  • Oracle: Pyth pull model. Hermes SSE stream for display prices, per-batch VAA payloads for settlement.
  • Infra: Docker images for the API, mirror bot, and static frontend; deployed on Railway.

Deployed contracts

Arbitrum Sepolia (chain id 421614):

Contract Address
ClearingHouse 0xE76F8a552896B01AcdEcdE28F429CAcaF42f7bfB
USDCMarginVault 0xBE12e78E49E573E6D006F1E90473EA44415806A8
MockUSDC (public mint faucet) 0xC381AADCf93839E456357feCC57a0eC1574665f9
OracleAdapter 0xf9ec765939C16a92BDeb24e681123651856De54c
FundingEngine 0x3c1231Fbde68465047e4064343a9B987C4f6b737
MarketRegistry 0x8497Cb7B3b830BBe456eBbF16C90d1dF2BF67821
InsuranceFund 0xbae7D477B76Cb1ea2B6A0863e3bA9189461a4fe4
BadDebtWaterfall 0xB838B9b6096A3B8B8839c791DbB497BC9f941D3A
AccessController 0xec4AC4ABD73997758673Dcea703DbD07F5b4B4CD

Markets: BTC-PERP, ETH-PERP, SOL-PERP. The canonical list lives in contracts/deployments/arbitrum-sepolia.json, written by the deploy script.

Credits

Frontend design by Marsgo.

Disclaimer

Testnet only. Unaudited. Built for learning, not for real funds. MockUSDC has an open mint, the deployer EOA holds every admin role, and several protocol pieces (on-chain liquidation, funding rate governance) are intentionally incomplete. See docs/known-limitations.md before assuming anything.

License

MIT

About

하이브리드 무기한 선물 DEX. 오프체인 Rust 매칭 엔진, 온체인 정산은 Arbitrum Sepolia. Solidity/Foundry, Pyth 오라클, EIP-712 주문. 테스트넷 전용

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages