Skip to content

User Flow

This page explains the bridge from the end-user perspective, keeping the actual protocol stages visible rather than abstracting them away.

Zink-specific

The Zink Bridge is not an instant swap. A user-initiated transfer moves through five discrete on-chain state transitions across two chains. Each stage is independently observable.

The protocol stages a user transfer goes through

1. deposit

The user submits a deposit instruction on the source chain.

What happens on-chain:

  • The user's tokens are transferred into the token-pair vault (or burned, if the pair uses MintBurn mode).
  • A fee is collected from the user in native SOL. The fee covers a flat fee configured on the Bridge, rent for the new DepositEntry, and rent for a potential token account on the destination chain. Part of this fee may be refunded during cleanup depending on what was actually created.
  • A new DepositEntry is appended to the DepositTracker with status Initialized.
  • The entry records refund_to, destination, mint, other_chain_mint, amount, and min_amount.

The min_amount field lets the user specify a minimum acceptable amount after any fee adjustments. If the destination-side result would deliver less than min_amount, authorities can reject the entry.

After this step, the user's tokens are locked and the transfer is visible on the source chain. Nothing has happened on the destination chain yet.

2. ack_deposit

Bridge authorities observe the new deposit on the source chain and submit ack_deposit on the destination chain.

What happens on-chain:

  • If no WithdrawEntry exists for this deposit yet, one is created in the destination-side WithdrawTracker with status Voting.
  • Each authority's vote carries a weight. When cumulative weight from agreeing authorities meets the bridge threshold, the entry transitions to Finalized with a computed DepositResult.

The DepositResult is either:

  • Confirmed — includes the confirmed amount and whether a token account was created on the destination chain.
  • Rejected — includes a DepositRejectionReason such as InsufficientFunds, LimitExceeded, TokenPairFrozen, TokenPairNotFound, or InternalError.

Bridge-specific

A deposit that was accepted on the source chain can still be rejected during ack_deposit if, for example, the token pair is frozen or a rate limit is exceeded on the destination chain at the time authorities process it. Rejected deposits are refunded during cleanup.

3. withdraw

After the destination-side WithdrawEntry is finalized with DepositResult::Confirmed, the withdrawal becomes executable.

What happens on-chain:

  • Tokens are released from the destination vault (or minted, for MintBurn pairs) to the destination address recorded in the entry.
  • The withdraw instruction is permissionless — anyone can call it for a finalized, confirmed entry, not just the original depositor.
  • This is the step users perceive as "the bridge completing."

If the result was Rejected, no withdrawal is possible for that entry. The depositor's recourse is the cleanup/refund on the source chain.

4. ack_withdraw

Authorities observe the finalized destination-side outcome and relay it back to the source chain via ack_withdraw.

What happens on-chain:

  • The original DepositEntry transitions from Initialized into Voting as authorities submit their observations.
  • Once enough authority weight agrees, the entry moves to Finalized with the observed DepositResult.

This step closes the information loop: the source chain now knows what happened on the destination chain.

5. cleanup_deposit

Once the source-side deposit entry is finalized, cleanup can run.

What happens on-chain:

  • If the deposit was confirmed, excess fees are refunded to refund_to. The refund amount depends on whether a destination-chain token account was actually created (if not, that portion of the fee is returned).
  • If the deposit was rejected, the escrowed tokens are returned to refund_to along with applicable fee refunds.
  • The entry's cleanup_completed flag is set to true.
  • Like withdraw, cleanup_deposit is permissionless.

What users should expect

  • The bridge is multi-transaction. A complete transfer involves at least three on-chain transactions (deposit, withdraw, cleanup) plus authority activity.
  • Transfer completion depends on authority observation and voting, not just the initial deposit. If no authorities are online, the transfer stalls after step 1.
  • Timing is variable. The authority polling interval, voting threshold, and network conditions all affect how quickly each phase completes. There is no guaranteed finality timing.
  • A deposit can be rejected after the user has already locked tokens. The refund path is cleanup, not an immediate revert.

Zink recommendation

If you build a UI on top of the bridge, surface the actual protocol state. At minimum, distinguish: deposit submitted → authority voting in progress → withdrawal available → withdrawal executed → source-side finalized → cleanup complete. Collapsing these into a single progress bar hides the information operators and users need to diagnose stalls.

Practical reading order

Zink is a general-purpose SVM network for programs, operators, and bridge integrations.