The bridge
Lock-on-Solana / mint-on-null, burn / claim, single-operator trust — and what is still pending.
The bridge connects null to Solana: lock SOL in a vault on Solana → credit native balance on null; burn native balance on null → release SOL from the vault.
Real deployment is pending
The deployable Solana vault program lives in programs/bridge-vault/ but is
not deployed to a real validator in the current build — see "Pending" below.
Everything described here runs end-to-end against a litesvm-backed Solana
simulator (solana-sim) with the same wire formats, real Ed25519 attestation
verification, real SOL custody, and real replay protection.
Trust model
The bridged asset is native SOL (no SPL token yet). It is a single-relayer model: the relayer holds the chain sequencer key, and the Solana vault trusts that one pubkey. This mirrors the fact that the PoA sequencer is already a single trusted operator — there is no fake decentralized proof scheme layered on a centralized chain.
Solana → null (deposit)
- A user deposits SOL into the vault on Solana (CPI transfer in,
DepositEventemitted via log data). - The relayer observes the deposit and calls the privileged
bridgeMintCredit(destination, amount, deposit_nonce, attestation)on null, authorized by a sequencer signature over the mint attestation message. - null credits
destination. The credit is idempotent per Solana deposit nonce — a replayed deposit is rejected (-32010), so no deposit is credited twice.
null → Solana (withdraw)
- A burn is a normal signed transaction whose single instruction targets the
builtin
BRIDGE_PROGRAM_ID. The node verifies the burner's signature, debits the burner, assigns a monotonic burn nonce, and appends aBurnRecord. - The relayer reads the burn journal, signs a claim attestation, and submits a
vault
claimon Solana, which pays out from the vault PDA. The claim is idempotent per burn nonce (a per-nonce receipt PDA whose creation fails on replay).
Supply accounting & backing guard
bridge_minted_total and bridge_burned_total are persisted;
netBacking = minted − burned. A burn is rejected if amount > netBacking —
the chain will never emit a burn the vault cannot honor, which also stops
airdropped/unbacked funds from being withdrawn through the bridge. The invariant
vault.bridged_balance == minted − burned holds after each settled round trip and
is asserted by the end-to-end test.
Pending (WSL / real-validator debt)
Two things are not exercised in this build, honestly:
- A real vault deployment.
cargo build-sbfcannot compile an on-chain program in the current dev environment (no MSVC host toolchain for platform-tools), andsolana-test-validatorcannot boot there. So the vault runs as asolana-simbuiltin with identical wire formats. - Remediation is documented: on Linux/macOS/WSL2 (or with MSVC + Developer
Mode),
cargo build-sbf && solana program deploy, boot a real validator, and point the relayer at it. The relayer needs two small changes for the real program — derive the vault PDA and prepend the Ed25519 precompile instruction to the claim.