Skip to content
helixLaunch

Docs

Bridge

In from Solana, out to Solana

The bridge moves tokens between the HELIX standard and Solana's token programs, one for one, in both directions. What goes in sits in a vault the program owns; what comes out is minted against it. There is no bridge fee: only the network fee and, the first time a token crosses, the rent of the accounts it needs.

  1. register_wrapper (once per mint, by whoever bridges it first) creates the wrapper, its HELIX mint and the vault, which is the wrapper's associated token account. The HELIX mint's name, symbol and uri are read on chain from the token's own metadata (its Token-2022 metadata extension or its Metaplex metadata account), never typed in, so nobody can register USDC under another name. A token with neither gets “Bridged token”.
  2. wrap(amount) moves the tokens into the vault with TransferChecked and mints, on HELIX, exactly what the vault received (a Token-2022 transfer fee is taken before it arrives).
  3. unwrap(amount) burns the HELIX tokens and pays the originals back from the vault, signed by the wrapper.

A wrapped HELIX mint has no hook, no freeze authority and no metadata authority; its mint authority is the wrapper, which signs nothing outsidewrap. Anyone can open a pool for it with create_pool.

  1. create_mirror (once per token) creates the mirror and its Token-2022 mint, with the metadata-pointer extension pointing at itself and the token-metadata extension holding the HELIX token's name, symbol and uri: wallets list it, and anyone can open a pool for it on another Solana DEX; Jupiter can route it once it has a pool somewhere Jupiter indexes. Its mint authority is the mirror; it has no freeze authority. A launch can be mirrored once it graduated, so the curve stays the only market before then.
  2. bridge_out(amount) moves the HELIX tokens, through the token's hook, into the mirror's vault holding, and mints the same amount of the mirror to the sender's Token-2022 account (what the vault received, if a hook takes a cut).
  3. bridge_back(amount) burns the mirror tokens (the owner signs) and returns the HELIX tokens from the vault, through the hook.
AccountAddressSizeRent
Wrapper["wrapper", spl_mint]192 B0.0022 SOL
Wrapped HELIX mint["wrapped", spl_mint]448 B0.004 SOL
Vault (in)the wrapper’s associated token account165 B+paid to the token program
Mirror["mirror", helix_mint]160 B0.002 SOL
Mirror mint["mirror-mint", helix_mint]234 B + metadataabout 0.004 SOL
Vault (out)["holding", helix_mint, mirror]184 B0.0022 SOL
InstructionTag
register_wrapper50
wrap(amount)51
unwrap(amount)52
create_mirror53
bridge_out(amount)54
bridge_back(amount)55

A Token-2022 mint with any of these extensions is refused, because each could freeze, seize or block what the vault holds:

  • permanent delegate (anyone it names can move the vault's tokens);
  • transfer hook (another program could refuse the vault's transfers);
  • non-transferable, default account state (frozen accounts), pausable, permissioned burn;
  • confidential transfers and confidential mint/burn (the vault couldn't see its balance).
  • A HELIX token's rules run on HELIX. Its burn, creator fee and holder fee apply to trades on the HELIX DEX; its SPL mirror trades freely elsewhere without them.
  • The mirror's vault is left out of holder rewards, like the pool: rewards go to holders on the HELIX standard. Bring a mirror back to earn them.
  • A creator lock or an early-buyer lock still holds: locked tokens can't be bridged out, because the transfer into the vault is refused.
  • A wrapped token can't be mirrored (unwrap it instead), so nothing goes round in circles.
bridge out with @helixfi/sdk
import { ix, mirrorAddress, mirrorMintAddress, holdingAddress, ataAddress, hookAccounts, TOKEN_2022_PROGRAM_ID } from '@helixfi/sdk';

const mirror = await mirrorAddress(mint);
const mirrorMint = await mirrorMintAddress(mint);
const a = {
  owner, helixMint: mint, mirror, mirrorMint,
  vault: await holdingAddress(mint, mirror),
  ownerHolding: await holdingAddress(mint, owner.address),
  ownerToken: await ataAddress(owner.address, mirrorMint, TOKEN_2022_PROGRAM_ID),
  hook: await hookAccounts(mint, mintAccount), // the kit needs the launch; an external hook its accounts
};
const ixs = [
  ix.createMirror({ payer: owner, helixMint: mint, mirror, mirrorMint, vault: a.vault, launch }), // first time only
  ix.createAtaIdempotent({ payer: owner, ata: a.ownerToken, owner: owner.address, mint: mirrorMint, tokenProgram: TOKEN_2022_PROGRAM_ID }),
  ix.bridgeOut(a, amount),
];

Bridge in is the same shape with ix.registerWrapper, ix.wrap and ix.unwrap. See the SDK and the bridge page.