Wallet Bridge

The bridge in full: the deposit record and its relay anchor, the withdrawal encoding and leaf commitment, the proof format, what a pause may and may not touch, and the one key that reaches a proven withdrawal.

The bridge application is at walletbridge.org. Everything below it, the portal program, the forced-inclusion inbox, the settlement program and the node's proof endpoints, existed before the application did. What did not exist was a way to use any of it without a keypair file and a command line.

The same key works on both sides

A deposit credits a Solana public key on the Layer 2, so the wallet that deposited can sign the Layer 2 withdrawal later. The Layer 2 accepts real Solana wire transactions, which is why the bridge needs nothing from a wallet beyond signTransaction, and why the application never calls signAndSendTransaction. There is no separate Solieum account to create and no bridged-asset ticker to learn.

Six steps, and who signs each one

StepWhereSigned by
Deposit: lock lamports in the vault and enqueue the creditSolanaYour wallet
Watch the entry get included and the credit landNobody
Withdraw: commit a withdrawal leaf into the L2 state treeSolieumYour wallet
Prove: present the inclusion proof against a final rootSolanaAnyone
Finalize: the vault pays the recipient after the air gapSolanaAnyone
Refund: take back a deposit the sequencer never includedSolanaAnyone

The last three take no privileged key. If the application disappears, a withdrawal in flight is still completable by anyone holding its id, and the payout can still only reach the recipient named inside the commitment.

Deposits

A deposit is a forced-inclusion entry, not an event for a watcher to notice. The alternative, watching an event or adding per-deposit records to the portal, would have created a second queue with its own deadline, watermark and fault rule: a copy of the inbox, drifting from it.

The portal's deposit instruction does three things in order:

  1. Transfers the amount to the vault.
  2. Transfers the inbox's minimum inclusion fee plus the entry's rent from the depositor to a relay address, a program-derived address seeded [b"relay"], system-owned with no data.
  3. Calls the inbox's enqueue instruction with the relay as the signing submitter and a 94-byte deposit record as the payload:

The relay's address is the Layer 2's trust anchor. The node credits an inbox entry as a deposit only when the entry's submitter is that relay address. Only a call through the portal program can sign for it, and the portal only signs after the vault has been credited. Anyone enqueueing a deposit-shaped payload from another address is simply submitting a forced transaction that fails to parse as a deposit, and it is consumed as a no-op like any junk entry.

Because a deposit is an inbox entry, it inherits everything the inbox already has: a deadline fixed on chain, a fault against the chain for an entry left behind, published bytes, and a drain every block. And it inherits a way out. A deposit the sequencer never includes can be refunded from the vault by anyone once its deadline passes. Before this design a deposit was a one-way door, and that was the worst row in the project's own stuck-funds analysis.

Timing is dominated by Solana's own confirmation, well under a minute. On the current chain an enqueued entry is credited to the named recipient one block later, and that block settles on Solana.

Withdrawals

Initiation is an ordinary signed transaction

A withdrawal is a wire-format Solana transaction whose single instruction targets a reserved Layer 2 address, sha256("solieum-l2-bridge-v1"), with data:

signed by the account being debited. The node intercepts it before the runtime, which would otherwise refuse an unknown program. The flat fee is charged as for any transaction, the payer is debited the amount, and a leaf is inserted. Too little balance is a reported drop with the fee kept, like any failed instruction.

There is no new record kind. The bytes are published as an ordinary transaction and replay re-derives the leaf from them, so a verifier holds a signed authorization for every leaf it recomputes.

The leaf is exactly what the portal recomputes

KeyThe withdrawal id, in the same state tree as the accounts
Valuesha256("solieum-wd" ‖ id ‖ amount_le ‖ recipient), the portal's own commitment domain
Idsha256("solieum-wd-id" ‖ signature), unique and derivable from the published bytes

Leaves never expire. The portal's per-withdrawal record, created by the proof, is the double-pay guard.

The proof comes from the finalized block's tree

Sibling hashes change as other leaves change, so a proof is root-specific. The node rebuilds the state at the block whose root is final by replaying its own published log to that height, root-verified as every replay is, and proves from that tree. The wire format is the portal's:

Because every later root contains every earlier leaf, a holder can prove against any retained final root, which is what makes root rent reclamation safe.

What was tested, against the deployed program bytes

  • A deposit funds the vault.
  • A leaf is committed in a settled root.
  • The root finalizes after the window.
  • A proof before finality is refused.
  • An inflated claim riding the honest proof bytes is refused.
  • The exact claim is accepted.
  • A second proof of the same id is refused.
  • Payout before the delay is refused.
  • On time it pays exactly once, to the recorded recipient, and cannot be repeated.

The full sequence, with its waits

  1. Initiate on the Layer 2. Balance debited, leaf committed, lands in a block like any transaction.
  2. Wait for the root. That block's root is committed under bond, then waits out the challenge window, 48 hours at the 400 millisecond target.
  3. Prove on Solana. The portal verifies the inclusion proof against that final root, with the same verifier the protocol's test gate runs.
  4. Wait out the air gap. 24 hours by the mainnet design.
  5. Finalize. The vault pays the recipient. Anyone can send it; the funds can only go to the recipient inside the commitment.

About three days in total. Quote that, never the window alone.

This has been run end to end on public devnet. The first payout was on 7 September 2026, a liquidity provider reclaiming its float. An ordinary withdrawal walked the whole user path on 10 September 2026: initiated, debited, proven against the final root, held for the portal's delay, then paid. A second finalize fired a second later and was correctly refused as already paid, so the path is idempotent. Both were team addresses, so the bar this project has set for itself is unchanged: an exit by an unaffiliated user in a drill.

What a pause may and may not do

A pause mayA pause may not
Stop new depositsDelay a withdrawal that has already been proven
Stop new state root submissionsExtend a challenge window that has already started
Halt the sequencerPersist without an expiry and a public record

The first rule in the right column is enforced by construction rather than policy: the withdrawal path does not read the pause flag at all, so no setting of it can reach a proven withdrawal. The test that matters pauses the bridge, watches a deposit be refused, then pays out an already-proven withdrawal while it is still paused.

The guardian is 2-of-3 by the mainnet design and separate from the upgrade authority, and the program refuses to install one that is not. Pauses expire on their own.

The one key that reaches a proven withdrawal

It is not the pause. It is the air gap, and it is on this page rather than in a changelog, because a safety section listing only the reassuring mechanisms is not a safety section.

Inside the delay between proving and payout, a guardian may deny a settlement root:

  • Denial creates a marker account for that root number. Its existence is the denial; there is no flag to unset.
  • Both finalize paths refuse while it exists, lamports and tokens alike, and proving refuses too, before reading the proof, so a denial is not a race an attacker can re-enter.
  • It names a root, never a withdrawal id. There is no instruction that can be pointed at a person.
  • It moves nothing. No path lets the guardian withdraw, redirect, or change a recipient.
  • The remedy is permissionless: anyone, not only the guardian, reopens an affected unpaid claim, which closes its record and returns the id. Your leaf never expired, so you prove the same withdrawal against the next honest root.
  • A denial is permanent and public, and the count of them is readable on chain.

What it costs you if it is ever used is the time to prove again, not your funds. It exists because the challenge window answers only whether a root was challenged, and cannot answer whether the dispute machinery itself was sound.

Permissionless exit

If Solieum stops entirely, the sequencer gone and the operator unreachable, you prove what you own against the last final root and withdraw on Solana. No cooperation, no permission.

The on-chain side exists and works, demonstrated end to end including the refusal of an inflated claim riding a genuine proof. What remains open is public tooling for building your own proof without the operator's node, and a drill in which an unaffiliated person does it. Until then, treat this as mechanism built rather than exit proven.

What the bridge does not do

  • SPL tokens are not credited on the Layer 2 yet. A token deposit emits an event; the L1 half of token withdrawal exists, but there is no Layer 2 token state to initiate from. Only SOL crosses today.
  • There is no messenger contract and no general message passing. An earlier version of this page described one. It does not exist, and arbitrary cross-layer messaging is not part of the current design.
  • There is no validator network watching the bridge, and no multisig holding user funds. Both were described in an earlier version and both are wrong in a way worth correcting explicitly, because they describe a weaker system that sounds stronger. There is no signer set on the withdrawal path at all.
  • Deposit caps and withdrawal velocity limits are planned, not built.

Fast exits

Three days is a long time to hold an asset you have decided to leave with. A fast-exit provider buys your pending withdrawal, pays you now at a spread, and waits out the window itself.

This needs no protocol change, and the shorter window is what makes the market cheaper: 48 hours rather than seven days cuts a provider's capital lock-up from eight days to three. It is also not underwritten by anybody today, and the provider on the devnet chain is the team's own. The honest phrasing is that a 48-hour window clears the way for a fast-exit market, not that Solieum provides one.

Fees on the bridge

Nothing beyond Solana's own transaction fee on the canonical path in either direction. A fee at the door is the wrong place to earn, and it would be the first thing a new user meets. A fast exit costs whatever spread the provider charges, in the asset withdrawn. Any future fee on token bridging is taken in the token bridged, capped, and governable. See Fees, Economics and the Token.