← Index
Source: docs/features/jayverse-token-bridge.md (auto-generated by scripts/generate-docs-html.mjs — edit the .md, not this file)

Jayverse — JYVE token + exchange + intra-bridge

Purpose: define an ecosystem ERC-20 (JYVE) used across Jayverse services, a tiny on-chain exchange (mini-AMM) that gives JYVE a readable price, and a minimal, dev-grade bridge to move it between jay's local Anvil fork and Sepolia. Token, exchange, and bridge are one economic unit, so they live together in a single jayverse-token repo (as packages), not three repos (jay, 2026-09-08). Design draft for review — nothing here is built yet.

Source: ../tasks/09-02-jayverse.md §7 "Intra Jayverse Bridge" and jay's comment there ("We can create an ERC coin used in our ecosystem like JVRS or JVS… bridged between my Anvil chain and Sepolia. Show me some imaginary scenario."). Hub: README.md.

Note on scope vs §7: the plan's §7 records a "no new token" decision (the intra-ledger is USDC balances in a shared vault). This doc explores the opposite branch jay asked for — an actual ecosystem token plus a real cross-chain hop — as a parallel design for jay to compare against the ledger-only approach. It does not overturn §7; it gives the token option a concrete shape to review.


Phases (build order)

Phase Focus What we implement
1 (MVP) Token + exchange JYVE.sol (ERC-20, MINTER_ROLE, per-address + global mint caps); Exchange.sol constant-product JYVE/USDC pool with addLiquidity/removeLiquidity/swap/getPrice, pool seeded at deploy so a price exists from block one.
2 Intra bridge BridgeLock / BridgeMint (or the relayer-script variant): lock-and-mint / burn-and-release between the Anvil fork and Sepolia; idempotent relayer keyed by transfer id; processed[id] guard; invariant + reconciliation cron.
3 Real cross-chain graduate to CCIP for arbitrary cross-chain messages, Circle CCTP for native USDC (burn-and-mint, no wrapped USDC), and xERC20 / ERC-7281 for JYVE (a sovereign bridged token with per-bridge mint/burn rate limits, instead of lock-and-mint wrapping) — where a service truly leaves the home chain.

1. What we build (basic feature)

Three small pieces, deliberately minimal:

  1. JYVE — an ERC-20 (Jayverse token). Standard OpenZeppelin ERC-20, 18 decimals, symbol JYVE (read "jive"), name "Jayverse". Renamed from the JVRS/JVS jay first suggested — JYVE reads as a word and is far easier to say (jay, 2026-09-08). It is the unit of account inside the ecosystem: verex rewards, persona rentals/payments, and game prizes are denominated and paid in JYVE. On testnet/dev it is mintable by an owner/faucet role (see §6); it is not a real-money asset.
  2. A minimal on-chain exchange (mini-AMM) — a constant-product JYVE/USDC pool. JYVE is a token we invented, so it has no external market an oracle could report — an oracle only relays a price that already exists somewhere liquid. So the pool itself is the price: price = usdcReserve / jyveReserve. Anything that needs a JYVE price (the wallet's USD display, the bridge's value readout, a portfolio view) reads the pool ratio on-chain. This is the honest way to price a self-made token, and a clean learning build (x·y=k, add/remove liquidity, swap).
  3. A minimal bridge to move JYVE between jay's local Anvil fork of Sepolia (chain id 11155111) and real Sepolia (also 11155111). Because both report the same chain id, the bridge is keyed by RPC endpoint / deployment, not by chain id — see the honesty note in §6. Pattern: lock-and-mint / burn-and-release driven by a single trusted relayer worker.

Keep both basic. No governance, no fee market, no multi-hop routing. The bridge is a developer convenience for testing cross-chain UX, not a trustless product.


2. Imaginary scenario

Meet Mina, a Jayverse user, working against the local dev stack (Anvil fork of Sepolia).

  1. She wins on verex. Mina holds a YES position on a verex market ("Will it rain in Seoul this weekend?"). The market resolves YES. Verex settles her winnings and pays out 120 JYVE to her wallet on the local Anvil chain. In the portal her balance ticks from 0 → 120 JYVE.
  2. She rents a persona. Mina wants "Startup-Mentor" for an hour. The persona service quotes 40 JYVE. She confirms; the wallet service signs an ERC-20 transfer of 40 JYVE from her wallet to the persona's payment address. Balance: 120 → 80 JYVE. The persona unlocks for the session.
  3. She bridges to Sepolia. Mina wants 30 JYVE on real Sepolia so a friend on the shared testnet can see it. In the portal she opens Bridge, picks source = Local (Anvil fork), dest = Sepolia, amount = 30. Before she signs, the wallet's <JayverseSign> simulate-before-sign previews the effect — lock 30 JYVE on Anvil → receive 30 on Sepolia — because a bridge (funds leaving a chain) is the scariest thing a user signs. She confirms one transaction and the 30 JYVE is locked in the bridge contract on the Anvil chain.
  4. The relayer does its job. The bridge relayer worker sees the Locked event, waits for confirmation, and mints (or releases from a pre-funded reserve) 30 JYVE to Mina's address on Sepolia. The portal shows: Locked ✓ → Relaying… → Minted ✓. Sepolia balance: +30 JYVE. Local balance: 80 → 50 JYVE.
  5. Later, she bridges back. Mina sends 10 JYVE from Sepolia → Local. On Sepolia the bridge burns her 10 JYVE; the relayer releases 10 JYVE from the lock on the Anvil side back to her. Invariant holds: total locked on source always equals total minted on dest.

Every money-moving step above (win → pay → bridge) routes its signature through the Wallet service's simulate-before-sign (jayverse-wallet.md), and JYVE amounts can be shown in USD via the exchange price (§1.2) — verex → bridge → wallet cooperating as one flow.

No step requires Mina to understand that the "two chains" are really a fork plus its origin — the UX is identical to a real bridge, which is the point of building it.


3. What the web app shows (the exchange site)

The web app is a single token-exchange site: a swap-first UI over the JYVE/USDC pool (§1.2) with the bridge as a second tab, so "trade JYVE" and "move JYVE across chains" live in one place (jay, 2026-09-09). Two primary screens — Swap and Bridge — sit over a shared balance/activity shell.


4. The flow

Token

Standard ERC-20. Mint policy for a testnet/dev coin:

Bridge (honest description)

An Anvil fork of Sepolia is not an independent chain — it is a local copy seeded from Sepolia state, sharing chain id 11155111. So a "bridge" here cannot be a trustless light-client bridge; there is no independent consensus to verify. What we build is a lock-and-mint / burn-and-release scheme with a single trusted relayer (jay's worker). This is a dev convenience, not a production bridge — the relayer is fully trusted and there is no fraud proof.

Minimal mechanism:

   LOCAL (Anvil fork)                         SEPOLIA
  ┌──────────────────┐                    ┌──────────────────┐
  │  JYVE (ERC-20)   │                    │  JYVE (ERC-20)   │
  │  BridgeLock      │                    │  BridgeMint      │
  └────────┬─────────┘                    └─────────┬────────┘
           │ user: lock(30, to)                     │ mint(30, to, srcTxId)
           │  emits Locked(id, to, 30)              │  emits Minted(id)
           ▼                                        ▲
     ┌───────────────────────  RELAYER  ────────────────────────┐
     │  watch Locked → wait N confs → mint on dest (idempotent   │
     │  by id) ; watch Burned → release on source (idempotent)   │
     └──────────────────────────────────────────────────────────┘

  Direction reversed for Sepolia → Local:
     BridgeMint.burn(30) on Sepolia  →  BridgeLock.release(30) on Local

Real-chain path: when a service actually leaves the home chain (e.g. lands on Base per the plan), the transport is Chainlink CCIP, not this relayer — same lock/mint semantics, but CCIP provides the cross-chain messaging and security. This dev bridge exists only so the UX and accounting can be built and tested before CCIP is wired in.


5. Cooperate with existing services

Each service depends only on the JYVE contract + rails config; only the bridge screen and relayer touch the bridge contracts.


6. Implementation sketch

Repo layout: one jayverse-token repo with packages token/, exchange/, bridge/ (+ a shared relayer/ worker). One economic unit, always deployed together; a fresh clone builds all three.

New:

Reused:

Risk notes:

Open questions (for jay):

  1. Do we even need a real bridge for a fork? A fork already starts from Sepolia state. A faucet-mirror — mint the same JYVE balance on both networks via a script — may satisfy every dev/demo need with far less machinery. Real value of the lock/mint bridge is exercising the UX and accounting ahead of CCIP. Is that worth it now, or defer until a service truly leaves the home chain?
  2. JYVE vs §7's "no new token" decision — do we introduce JYVE ecosystem-wide, or keep USDC as the ledger unit and treat JYVE as a rewards/points token only?
  3. Mint authority — one shared treasury with MINTER_ROLE, or per-service minters (verex, game) with individual caps?
  4. Symbol — resolved (jay, 2026-09-08): JYVE (read "jive"), replacing the earlier JVRS/JVS.
  5. Pricing — resolved (jay, 2026-09-08): a JYVE/USDC mini-AMM in the same jayverse-token repo is the on-chain price source; an oracle is not used (it can't price a self-made token). Open sub-question: seed price + initial liquidity depth for the demo pool.

Chainlink's oracle stack is settlement-rail infrastructure this token consumes, not reimplements — see the umbrella map in README.md.

Deliberate non-use — pricing JYVE (the loud one). JYVE trades only in our own market, so it has no external price an oracle could report. Its price comes from the constant-product mini-AMM (price = usdcReserve / jyveReserve), never a feed. Reaching for an oracle here is a category error — an oracle relays an external truth, and a self-made token has none. (See §1.2 and §6.)

Every feed is a dependency with a failure mode — keep the "if wrong / late" guard in code, not only here.

Cross-chain message layer — rail choice, and toy-vs-rent (LayerZero / CCIP)

The bridge needs to carry a message across chains (Phase 3). Three options, three different answers — and naming the split matters because getting it wrong wastes the most time here.

The principle that outlives the rail choice: a message layer widens what you can reach, not where truth lives. Settlement finality happens on exactly one chain; every other chain is a display / deposit path. That is the 1:1 invariant restated — one side is the sole source of truth, the other a mirror.

Two silent traps, whichever rail you pick:

Trap Looks like The fix
Under-provisioned destination gas send succeeds, destination execution fails on another chain a retry story written before it's needed — the failure isn't visible at the call site
Untouched verifier config (LayerZero DVN / CCIP RMN) everything works record who verifies in the repo, plus a CI/test that asserts the live config matches — an unrecorded verifier is a trust assumption absent from every code review

The second trap is the Authority Auditor's domain: who am I trusting right now, and is it written down where a change would break?