--- title: SVM program description: "The Hular Solana program: instructions, events, and error codes." --- import { PROGRAM_SOLANA, ESCROW_SOLANA, TREASURY_SOLANA } from "/snippets/vars.mdx"; One Anchor program covers the Solana side, mirroring the EVM escrow and solver split. Deposits pay into an escrow, a program-derived account with seed `escrow`, and stay there until they settle past the deep-reorg check; refunds pay out of the same escrow with the program signing as its authority. The operator float lives in a plain treasury system account and its associated token accounts, and fulfillments are signed by the treasury key itself. Settled escrow funds move to the treasury through the release instructions. | | Address | | --- | --- | | Program id | {PROGRAM_SOLANA} | | Escrow (PDA, seed `escrow`) | {ESCROW_SOLANA} | | Treasury | {TREASURY_SOLANA} | Prefer the `router_address` (program id) and `treasury` returned on the quote and by `GetChains` over these constants. ## Deposit instructions ```rust pub fn deposit_token(ctx: Context, quote_hash: [u8; 32], amount: u64) -> Result<()>; pub fn deposit_native(ctx: Context, quote_hash: [u8; 32], amount: u64) -> Result<()>; ``` `deposit_token` transfers SPL tokens from the depositor's token account into the escrow's associated token account and emits `Deposit` with the amount actually credited, so transfer-fee mints are accounted at the escrow, not assumed. `deposit_native` transfers lamports to the escrow directly; the mint in its event is the default pubkey. ```rust pub fn deposit_swap( ctx: Context, quote_hash: [u8; 32], src_mint: Pubkey, src_amount: u64, min_bridge_out: u64, swap_data: Vec, ) -> Result<()>; ``` Invokes the aggregator program passed as `swap_program` with the caller-supplied accounts and data, then requires the escrow's token account to have grown by at least `min_bridge_out`, emitting `SwapDeposit` with the credited amount. `buildSvmSwapDeposit` in the SDK assembles this transaction from the `GetSwapInstructions` payload; see [Swap instructions](/api-reference/get-swap-instructions). ## Operator instructions Restricted to the treasury signer, listed for completeness. ```rust pub fn fulfill_token(ctx: Context, quote_hash: [u8; 32], amount: u64, gas_drop: u64) -> Result<()>; pub fn fulfill_native(ctx: Context, quote_hash: [u8; 32], amount: u64) -> Result<()>; pub fn refund_token(ctx: Context, quote_hash: [u8; 32], amount: u64) -> Result<()>; pub fn refund_native(ctx: Context, quote_hash: [u8; 32], amount: u64) -> Result<()>; pub fn release_token(ctx: Context, amount: u64) -> Result<()>; pub fn release_native(ctx: Context, amount: u64) -> Result<()>; ``` `fulfill_token` pays the recipient's token account from the treasury and optionally transfers `gas_drop` lamports to the recipient, requiring the recipient to be credited the full amount. The refund variants pay the depositor back from the escrow, with the program signing as the escrow authority. The release variants move settled deposits from the escrow to the treasury and are submitted by the operator once the released amount crosses a per-token threshold. ## Voucher redemption ```rust pub fn redeem_voucher( ctx: Context, id: [u8; 32], referrer: Pubkey, amount: u64, signature: [u8; 64], ) -> Result<()>; ``` Callable by anyone. The transaction must include an ed25519 verification instruction, before this one, over the voucher message (domain, chain, program id, id, mint, referrer, amount) signed by a registered voucher signer. A marker account derived from the id is initialized on redemption, so an id cannot be redeemed twice, and the amount is transferred from the treasury's token account to the referrer's via the program's delegate authority PDA. See [Referral program](/integration/referrals). ## Events | Event | Emitted by | | --- | --- | | `Deposit(quote_hash, mint, amount, from)` | `deposit_token`, `deposit_native` | | `SwapDeposit(quote_hash, mint, amount, from, src_mint, src_amount)` | `deposit_swap` | | `Fulfilled(quote_hash, mint, amount, recipient, gas_drop)` | `fulfill_token`, `fulfill_native` | | `Refunded(quote_hash, mint, amount, recipient)` | `refund_token`, `refund_native` | | `Released(mint, amount)` | `release_token`, `release_native` | | `VoucherRedeemed(id, mint, referrer, amount)` | `redeem_voucher` | The indexer matches `Deposit` and `SwapDeposit` against stored quotes by `quote_hash`. Native amounts carry the default pubkey as `mint`. ## Errors | Error | Cause | | --- | --- | | `Unauthorized` | An operator instruction signed by a key other than the treasury. | | `InvalidVoucherSignature` | No preceding ed25519 instruction matches a registered voucher signer. | | `ShortCredit` | The recipient was credited less than the transferred amount. | | `InsufficientOutput` | The swap credited the escrow below `min_bridge_out`. |